Перекрестные запросы в django

#django #django-models

Вопрос:

У меня есть две модели, как показано ниже

 class Watched(Stamping):
    user = models.ForeignKey("User", null=True, blank=True, on_delete=models.CASCADE,
                             default=None)
    count = models.PositiveIntegerField()


class Link(Stamping):
    ...
    user = models.ForeignKey(User,  on_delete=models.CASCADE, default=None)
    url = models.CharField(max_length=256, default=None)
    watched = models.ForeignKey(Watched, null=True, blank=True, on_delete=models.CASCADE, default=None)
    ...
 

Мой forms.py

 class SimpleLink(forms.Form):
    url = forms.URLField(max_length=256)
 

Пользователь может создать Link объект, и при выполнении некоторых условий объект будет добавлен Watched . Watched Модель содержит объекты, созданные разными пользователями.
Теперь я хочу отфильтровать Watched класс и захватить только объекты, созданные запрашивающим пользователем в Link модели, но я не знаю, как этого добиться. Любая помощь будет оценена по достоинству.
Пример того, чего я хочу достичь, таков…
Watched.objects.filter(Link.objects.filter(user=request.user) . Я знаю, что мой образец сумасшедший. Но из внешнего запроса я хочу захватить объекты ссылок, созданные пользователем, отправившим запрос

Комментарии:

1. Можете ли вы поделиться своей текущей формой?

2. Я отредактировал вопрос, чтобы включить форму

Ответ №1:

Вам нужно ограничить набор запросов в вашем ModelForm . А ModelForm будет, таким образом, выглядеть так:

 from django import forms

class LinkForm(forms.ModelForm):
    
    def __init__(self, *args, user=None, **kwargs):
        super().__init__(*args, **kwargs)
        if user is not None:
            self.fields['watched'].queryset = Watched.objects.filter(
                link__user=user
            )

    class Meta:
        model = Link
        fields = ['url', 'watched'] 

На наш взгляд, затем мы можем задать user объект:

 from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render

@login_required
def some_view(request):
    if request.method == 'POST':
        form = LinkForm(request.POST, user=request.user)
        if form.is_valid():
            form.instance.user = request.user
            form.save()
            return redirect('name-of-some-form')
    else:
        form = LinkForm(user=request.user)
    return render(request, 'some-template.html', {'form': form}) 

Для представления на основе классов мы можем переопределить .get_form_kwargs(…) метод [Djangod-doc]:

 from django.contrib.auth.mixins import LoginRequiredMixin

class SomeView(LoginRequiredMixin, CreateView):
    form_class = LinkForm
    
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form) 

Комментарии:

1. На мой взгляд, есть ли способ, которым я могу сделать что-то подобное Watched.objects.filter(Link.objects.filter(user=request.user) . Я знаю, что мой образец сумасшедший. Но из внешнего запроса я хочу захватить Link объекты, созданные пользователем, отправившим запрос

2.@Сэмми: да, вы можете фильтровать с Watched.objects.filter(link__user=request.user) помощью . Таким образом, это приведет к извлечению всех Watched объектов, для которых существует связь Link с as user request.user .

3. Я это должно быть добавлено в качестве ответа, чтобы я мог отметить его

4. @Sammy: обновлена фильтрация в форме модели.