简体   繁体   中英

django 2 - User and userprofile models, how to obtain all fields in a single query?

Update and solution below.

I've been looking for a solution but I'm not finding anything that sticks out.

I've created a Profile model which is linked to the standard User model via one-to-one field which is working in admin. I want to pull all fields/data for both models into a single queryset. I'm trying to create a user editing form and I want to pull in all fields for User and Profile based on the current logged in user and display those fields which I will have a page to edit and save those fields.

What are the best options to achieve this, simple is better.

class Profile(models.Model):
    address = models.blablabla
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')

def profile_edit(request):
    form = UserProfileForm(request.POST or None)
    instance = Profile.objects.all().filter(user__username=request.user).values # This is the place I need to create a single queryset.
    if request.method == "POST" and form.is_valid():
        form = UserProfileForm(request.POST, instance=instance)
        user_form = form.save()
        print("POST event")
    else:
        form = UserProfileForm(instance=instance)
        print(form)
    return render(request, 'frontend/profile_edit.html', {'form': form})

I'm manually creating the forms in the template so I would like to have something like {{ form.username }} {{ form.profile.address }} or something like that. I'm likely doing things poorly, I'm new to django.

UPDATE Complete solution

Complete steps to gain access to user and profile models in code and template.

I decided not to replace the User model with my own in case I missed out on features provided by django. It also seemed to complicate things that might hurt later on. So I've gone with the separate UserProfile model and attached it to the User model. Here is what I did for future readers.

models.py

from django.db.models.signals import post_save

class UserProfile(models.Model):
#take note of the related_name='profile' this is used to reference the fields in code and template.

#Each field of type 'text' I added default='' at the end, I got an error when it was int based so I removed the flag for that field.  I read this might cause an error when you try and auto-create the profile, see what works for you and you might not want it.

        user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') 
        country = models.CharField(max_length=2, blank=True, null=True, default='')
        ...

    # Auto-create the profile upon user account creation.  It's important to start with a fresh database so the user and profile ID's match.

        def create_user_profile(sender, instance, created, **kwargs):
            if created:
                UserProfile.objects.create(user=instance)

        post_save.connect(create_user_profile, sender=User)
    # Create your models here.

#In code, you can access your user and profile field data like so.

request.user.profile.fieldname
request.user.fieldname

In template you can do the same

{{ user.fieldname }}
{{ user.profile.fieldname }}

There's no need for a query here at all - you don't want a queryset, you want a single instance.

In this case, request.user.profile will give you the entire Profile object related to the current user.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM