Generic Relations and Unlimited Phone Numbers


#1

I read your article about generic relations and the fact that it will slow things down and become more complex. I need to be able to store unlimited amount of phone numbers per user. Like Google Contacts let’s you do.
I don’t see another way around this?

Also, how would I output that in the Admin?


#2

I think I got it figured out, just worried about performance.

One issue I am having is that when I go to add a user in the admin, under the Phones section it wants a user each time. How do I not show that and make sure it puts in the ID of the new user that is being created?


(Arvie San) #3

Is many-to-many field not applicable on the situation? since you just need to add one type of data which is phone number?


#4

No, because one person can have many phones, but many people can’t have the same phone.


(Vitor Freitas) #5

Just an associative model with a foreign key pointing to the user model would do:

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

class Phone(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name='phones')
    phone = models.CharField(max_length=30, unique=True)

Then on Django Admin you can let the users add the phones directly on the person views:

admin.py

class PhoneInline(admin.TabularInline):
    model = Phone

@admin.register(Loja)
class PersonAdmin(admin.ModelAdmin):
    list_display = ['first_name', 'last_name']
    inlines = [PhoneInline,]

You can also use admin.StackedInline instead of admin.TabularInline


#6

Wow, ok, thanks. Will try that. Easier than what i was doing.


#7

ok, so I got this work as above. One problem I see is that when the new phone numbers are shown, it shows the actual PK which is a UUID. Assume it’s coming from the str_() in the model. How do I get it to show likes it was before, which is the count. Phone #1, #2 etc.

image

model.py

class Phone(models.Model):
PHONE_TYPE_CHOICES = (
    (1, 'home'),
    (2, 'mobile'),
    (3, 'fax'),
    (4, 'other'),
    )
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
phone_type = models.PositiveSmallIntegerField(choices=PHONE_TYPE_CHOICES, null=False, blank=False)
phone_number = PhoneNumberField(blank=True, null=True)
phone_extension = models.CharField(max_length=10, blank=True, null=True, verbose_name=_("Phone Ext."))

class Meta:
    unique_together = ('user', 'phone_type', 'phone_number')

def __str__(self):
    return str(self.id)

admin.py

from django.contrib import admin
from django.contrib.auth import admin as auth_admin, get_user_model
from phonenumber_field.formfields import PhoneNumberField
from phonenumber_field.widgets import PhoneNumberPrefixWidget

from corfix.users.models import Phone

User = get_user_model()


class PhoneInline(admin.StackedInline):
    model = Phone
    formfield_overrides = {
    PhoneNumberField: {
        'widget': PhoneNumberPrefixWidget
        },
    }


@admin.register(User)
class UserAdmin(auth_admin.UserAdmin):
inlines = [PhoneInline, ]
fieldsets = (("User", {
    "fields": ("name", "client", "user_type"),
    }),) + auth_admin.UserAdmin.fieldsets
list_display = ["username", "name", "client", "user_type"]
search_fields = ["name", "username", "email"]