首页 > 解决方案 > (Django) Limited ForeignKey choices by Current User

问题描述

Update

Thanks to Michael I was able to get this to work perfectly in my CreateView, but not in the UpdateView. When I try to set a form_class it spits out an improperly configured error.

How can I go about filtering the ForeignKey in the updateview?

End Update

I have a feeling I'm missing something small here but I've been working on it for a while and can't figure it out.

I have an app called story universe where the user creates one with a name and description.

I then have a character creator class where the user can create a character within that universe. This all works fine, except when the user goes to create their character they see a list of all universes created by all users.

Then there are other apps that will also mimic what I'm trying to do with the character creator.

I need to limit the Story Universes to only those created by the currently logged in user.

I've tried a few different ways and had the most success with the following, but with this code, no Universe appears when trying to create a new character.

models.py:

class Universe(models.Model):
    user = models.ForeignKey(User,related_name='universe',on_delete=models.CASCADE)
    name = models.CharField(max_length=100, unique=True)
    description = models.TextField(max_length=2000,blank=True,default="")    

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('universe:singleuniverse',kwargs={'pk': self.pk})

    class Meta:
        ordering = ['name']
        unique_together = ['user','name']

class Character(models.Model):
    user = models.ForeignKey(User,related_name='characters',on_delete=models.CASCADE)
    universe = models.ForeignKey("story_universe.Universe", on_delete=models.CASCADE)
    name = models.CharField(max_length=255,unique=True)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('character_developer:singlecharacter',kwargs={'pk': self.pk})

    class Meta():
        ordering = ['name']
        unique_together=['user','name']

views.py:

class CreateCharacter(LoginRequiredMixin,generic.CreateView):
    template_name ='character_developer/character_create.html'
    form_class = CreateForm

    def get_form_kwargs(self):
        kwargs = super(CreateCharacter,self).get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

    def form_valid(self,form):
        self.object = form.save(commit=False)
        self.object.user = self.request.user
        self.object.save
        return super().form_valid(form)

forms.py:

class CreateForm(forms.ModelForm):

    def __init__(self,*args,**kwargs):
        user = kwargs.pop('user')
        super(CreateForm,self).__init__(*args,**kwargs)
        self.fields['universe'].queryset = Character.objects.filter(user=user)

    class Meta:
        model = Character
        fields = ('universe','name')

标签: pythondjango

解决方案


您需要对您的CreateForm课程进行轻微更改forms.py

class CreateForm(forms.ModelForm):

    def __init__(self,*args,**kwargs):
        user = kwargs.pop('user')
        super(CreateForm,self).__init__(*args,**kwargs)
        self.fields['universe'].queryset = Universe.objects.filter(user=user)

    class Meta:
        model = Character
        fields = ('universe','name')

然后,这会将返回的Universe对象拉入 Universe 字段,但仅适用于当前登录的用户。


推荐阅读