I have a problem with a queryset in one view. My idea is show all users who are not registered in a program, I put here the models:
models.py
class UCAUser(AbstractUser):
dni_cif=models.CharField(
max_length=9,
blank=True,
verbose_name="DNI/CIF"
)
class InscripcionRealizada(models.Model):
formulario = models.ForeignKey(Formulario)
inscrito = models.ForeignKey(UCAUser,related_name="inscripciones_realizadas")
fecha_registro = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Inscripción realizada"
verbose_name_plural = "Inscripciones realizadas"
def __str__(self):
return "{} - {} - {}".format(self.formulario.programa, self.formulario.edicion, self.inscrito)
You can see UCAUser and InscripcionRealizada are connected by InscripcionRealizada.inscrito field.
view.py
class InscribirUsuariosListView(ListView):
template_name = "inscripciones/InscribirUsuariolist.html"
model = UCAUser
group_required = ['Administrador']
login_url = "auth-login"
def get_queryset(self):
qs = super(InscribirUsuariosListView, self).get_queryset()
return qs.filter(UCAUser.objects.filter(inscripciones_realizadas__formulario!=self.kwargs['formulario_id']))
def get_context_data(self, **kwargs):
context = super(InscribirUsuariosListView, self).get_context_data(**kwargs)
context['formulario_id'] = self.kwargs['formulario_id']
return context
When I try this, I get an error:
not enough values to unpack (expected 2, got 1)
Any idea?
Related
I have a specific problem with my forms. I think it would be better to share my codes instead of explaining the problem in detail.
However, to explain in a nutshell; inside my model I have field OneToOneField and model of that field has inlineformset_factory form. My new model also has a form and I want to save both forms.
I get the following error when I want to save the offer update form:
TypeError at /ru/mytarget/offer-update/T2GTTT053E9/
AdminOfferUpdateView.form_invalid() missing 2 required positional arguments: 'request_form' and 'request_item_formset'
Models:
request.py
class RequestModel(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="customer_requests")
id = ShortUUIDField(primary_key=True, length=10, max_length=10, prefix="T", alphabet="ARGET0123456789", unique=True, editable=False)
status = models.BooleanField(default=True)
request_title = models.CharField(max_length=300)
......
updated_on = models.DateTimeField(auto_now=True)
published_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.request_title)
class Meta:
verbose_name_plural = "Requests"
verbose_name = "Request"
def get_absolute_url(self):
return reverse('mytarget:customer_request_details', kwargs={'pk': self.id})
class RequestItem(models.Model):
request_model = models.ForeignKey(RequestModel, on_delete=models.CASCADE, related_name="request_items")
product_name = models.CharField(max_length=300)
......
offer.py
class OfferModel(models.Model):
request_model_name = models.OneToOneField(RequestModel, on_delete=models.CASCADE, primary_key=True)
status = models.BooleanField(default=True)
offer_validity = models.CharField(max_length=50, blank=True)
......
updated_on = models.DateTimeField(auto_now=True)
published_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.request_model_name)
class Meta:
verbose_name_plural = "Offers"
verbose_name = "Offer"
def get_absolute_url(self):
return reverse('mytarget:admin_offer_update', kwargs={'pk': self.request_model_name})
Forms:
request_create_form.py
class CustomerRequestForm(forms.ModelForm):
disabled_fields = ("customer",)
class Meta:
model = RequestModel
fields = ("customer", "request_title", "delivery_time", "shipping_country", "shipping_address",
"preferred_currency", "shipping_term", "delivery_term")
widgets = {
'request_title': TextInput(attrs={'class': 'form-control tableFormInputs',
'placeholder': _('Example: Printers, Toner, and Cartridges')}),
......
}
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('customer')
super(CustomerRequestForm, self).__init__(*args, **kwargs)
self.fields['preferred_currency'].queryset = self.fields['preferred_currency'].queryset.translated().order_by("translations__currency_name")
self.fields['shipping_term'].queryset = self.fields['shipping_term'].queryset.translated().order_by("translations__shipping_term")
for field in self.disabled_fields:
self.fields[field].widget = forms.HiddenInput()
self.fields[field].disabled = True
class CustomerRequestItemForm(forms.ModelForm):
class Meta:
model = RequestItem
fields = ("product_name", "product_info", "target_price", "price", "quantity", "dimensions", "net_weight", "gross_weight",
"hs_or_tn_ved_code", "brand", "manufacturer", "origin_country", "manufacturer_address")
exclude = ()
widgets = {
'product_name': TextInput(attrs={'class': 'form-control tableFormInputs'}),
......
}
RequestItemInlineFormset = inlineformset_factory(RequestModel, RequestItem,
form=CustomerRequestItemForm,
extra=1,
can_delete=True
)
offer_update_form.py
class AdminOfferUpdateForm(forms.ModelForm):
disabled_fields = ()
hidden_fields = ("request_model_name",)
request_title = forms.CharField(required=False, widget=TextInput(attrs={'class': 'form-control tableFormInputs', 'placeholder': _('Example: Printers, Toner, and Cartridges')}))
......
class Meta:
model = OfferModel
fields = ("request_model_name", "offer_validity", ......
)
widgets = {'offer_validity': TextInput(attrs={'class': 'form-control tableFormInputs'}),
......
'is_detailed_offer': CheckboxInput(attrs={'class': 'form-check-input'}),
}
def __init__(self, *args, **kwargs):
super(AdminOfferUpdateForm, self).__init__(*args, **kwargs)
self.fields["preferred_currency"].choices = [(c.id, c.currency_name) for c in Currency.objects.all()]
self.fields["shipping_term"].choices = [(st.id, st.shipping_term) for st in ShippingTerm.objects.all()]
self.fields["delivery_term"].choices = [(dt.id, dt.delivery_term) for dt in DeliveryTerms.objects.all()]
self.fields["request_statuses"].choices = [(r.id, r.status) for r in RequestStatus.objects.all()]
for field in self.disabled_fields:
self.fields[field].disabled = True
for field in self.hidden_fields:
self.fields[field].widget = forms.HiddenInput()
Views:
offer_update_view.py
#method_decorator([login_required(login_url=reverse_lazy("accounts:signin")), user_is_superuser], name='dispatch')
class AdminOfferUpdateView(UpdateView):
model = OfferModel
form_class = AdminOfferUpdateForm
template_name = "mytarget/admin_offer_update.html"
def get_context_data(self, **kwargs):
context = super(AdminOfferUpdateView, self).get_context_data(**kwargs)
if self.request.POST:
context['request_form'] = AdminOfferUpdateForm(self.request.POST, instance=self.object.request_model_name)
context['request_item_formset'] = RequestItemInlineFormset(self.request.POST, instance=self.object.request_model_name)
else:
context['request_form'] = AdminOfferUpdateForm(instance=self.object.request_model_name)
context['request_item_formset'] = RequestItemInlineFormset(instance=self.object.request_model_name)
return context
def form_valid(self, form):
context = self.get_context_data()
request_form = context['request_form']
request_item_formset = context['request_item_formset']
with transaction.atomic():
self.object = form.save()
if request_form.is_valid() and request_item_formset.is_valid():
request_form.instance = self.object.request_model_name
request_form.save()
request_item_formset.instance = self.object.request_model_name
request_item_formset.save(commit=False)
for ri in request_item_formset:
ri.save(commit=False)
request_item_formset.save()
return super(AdminOfferUpdateView, self).form_valid(form)
def form_invalid(self, form, request_form, request_item_formset):
return self.render_to_response(
self.get_context_data(form=form, request_form=request_form, request_item_formset=request_item_formset)
)
def get_initial(self):
self.object = self.get_object()
if self.object:
return {"request_model": self.object.request_model_name, "request_item_formset": self.object.request_model_name}
return super().initial.copy()
def get_success_url(self):
return reverse('mytarget:admin_offer_update', kwargs={'pk': self.object.id})
I solved my problem. I created a button function that creates a new model with inheritance of other model fields. In this way, there is no need to edit the form of the other model inside the form of my current model.
Can you please tell me how to transfer the calendar to the form with a get request, with clicking on the days of the week and transferring to the form? There is a filtering for all fields at the same time now, only with the date of trouble (
Approximately how such a calendar can be transmitted? Thanks in advance.
class Traveller(models.Model):
title = models.CharField(max_length=30,default='',null=False)
origin = models.ForeignKey(Origin,on_delete=models.CASCADE,max_length=100,verbose_name= 'Источник',default='')
destination = models.ForeignKey(Destination,on_delete=models.CASCADE, verbose_name="Местонахождение",default='')
transport = models.ForeignKey(Transport,on_delete=models.CASCADE, verbose_name="Транспорт",default='')
passengers = models.ForeignKey(Passengers,on_delete=models.CASCADE, verbose_name="Пассажиры",default='')
url = models.SlugField(max_length=130, unique=True)
def __str__(self):
return self.title
class Meta:
verbose_name = 'Путешествие'
verbose_name_plural = 'Путешествие'
def get_absolute_url(self):
return reverse("traveller", kwargs={"url": self.url})
`views:
class FullTraveller:
def get_origin(self):
return Origin.objects.all()
def get_destination(self):
return Destination.objects.all()
def get_transport(self):
return Transport.objects.all()
def get_passengers(self):
return Passengers.objects.all()
class TravellerView(FullTraveller, ListView):
template_name = 'index.html'
model = Traveller
queryset = Traveller.objects.all()
paginate_by = 1
class FilterTravelView(FullTraveller,ListView):
def get_queryset(self):
if self.request.GET.getlist("origin") and self.request.GET.getlist("destination") and self.request.GET.getlist(
"transport") and self.request.GET.getlist("destination"):
queryset = Traveller.objects.filter(origin__in=self.request.GET.getlist("origin"),
destination__in=self.request.GET.getlist("destination"),
transport__in=self.request.GET.getlist("transport"),
passengers__in=self.request.GET.getlist("passengers"))
else:
queryset = Traveller.objects.filter(Q(origin__in=self.request.GET.getlist("origin")) | Q(
destination__in=self.request.GET.getlist("destination")) | Q(
transport__in=self.request.GET.getlist("transport"))| Q(
passengers__in=self.request.GET.getlist("passengers")))
return queryset
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context["origin"] = ''.join([f"origin={x}&" for x in self.request.GET.getlist("origin")])
context["destination"] = ''.join([f"destination={x}&" for x in self.request.GET.getlist("destination")])
context["transport"] = ''.join([f"transport={x}&" for x in self.request.GET.getlist("transport")])
context["passengers"] = ''.join([f"passengers={x}&" for x in self.request.GET.getlist("passengers")])
return context
forrm in template
`
```
```
I tried various options with widgets, but it didn’t work to insert them into the template
I am developing an online Book Store.
Here is the models:
class Author(models.Model):
name = models.CharField(max_length=250, unique=True)
class Publisher(models.Model):
name = models.CharField(max_length=250, unique=True)
class Book(models.Model):
author = models.ManyToManyField(Author, related_name='authors')
publisher = models.ForeignKey(Publisher, on_delete=models.PROTECT, blank=True, null=True)
isbn13 = models.BigIntegerField(unique=True)
name = models.CharField(max_length=500)
...
Here is the View:
class AuthorsListView(ListView):
model = Author
context_object_name = 'authors_list'
template_name = 'authors_list.html'
paginate_by = 500
class AuthorBooksListView(ListView):
model = Book
context_object_name = 'author_books'
template_name = 'author_books.html'
def get_queryset(self, **kwargs):
author_id = Author.objects.get(pk = self.kwargs['pk'])
qs = super().get_queryset(**kwargs)
return qs.filter(author = author_id)
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet
context['author'] = Author.objects.get(pk = self.kwargs['pk'])
return context
class PublishersListView(ListView):
model = Publisher
context_object_name = 'publishers_list'
template_name = 'publishers_list.html'
paginate_by = 500
class PublisherBooksListView(ListView):
model = Book
context_object_name = 'publisher_books'
template_name = 'publisher_books.html'
paginate_by = 20
def get_queryset(self, **kwargs):
publisher_id = Publisher.objects.get(pk = self.kwargs['pk'])
qs = super().get_queryset(**kwargs)
return qs.filter(publisher = publisher_id)
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet
context['publisher'] = Publisher.objects.get(pk = self.kwargs['pk'])
return context
class BooksListView(ListView):
model = Book
context_object_name = 'books_list'
template_name = 'books_list.html'
paginate_by = 100
class BookDetailView(DetailView):
model = Book
template_name = 'book_detail.html'
Here is the urls:
path('authors/', AuthorsListView.as_view(), name = 'authors_list'),
path('author/<int:pk>/', AuthorBooksListView.as_view(), name='author_detail'),
path('publishers/', PublishersListView.as_view(), name='publishers_list'),
path('publisher/<int:pk>/', PublisherBooksListView.as_view(), name='publisher_detail'),
path('', BooksListView.as_view(), name='books_list'),
path('book/<int:pk>/', BookDetailView.as_view(), name='book_detail'),
On the Book Detail Page I want to display:
Related books by the same author
Related books by the same publisher
How can I do this? Please help me.
I was trying to add these code to the BookDetailView:
def get_queryset(self, **kwargs):
book = Book.objects.get(pk = self.kwargs['pk'])
queryset = {
'books': Book.objects.all(),
'publisher_books': Book.objects.filter(publisher = book.publisher.id),
}
return queryset
But it gives me an error:
'dict' object has no attribute 'filter'
#djangodjarhes - Can you try the following? Ideally I modify the get_queryset if I want to change the way the queryset should be filtered other than the URL kwargs. For anything else, I override the get_context_data
def get_context_data(self, **kwargs):
context = super(BookDetailView, self).get_context_data(**kwargs)
book = Book.objects.get(pk = self.kwargs['pk'])
publisher_books = Book.objects.filter(publisher = book.publisher.id)
context["publisher_books"] = publisher_books
return context
In your case and feel free to correct me
queryset = {
'books': Book.objects.all(),
'publisher_books': Book.objects.filter(publisher = book.publisher.id),
}
This is not right. You are returning a dict when the get_queryset is supposed to return a queryset. You cannot return a dict. Either you change it to do this
queryset = Book.objects.filter(publisher = book.publisher.id)
return queryset
or use get_context_data if you want to return a dict.
I created a CustomUser as follows, however, I am not able to use the CustomUser functions in Views as I get the error message "get_first_name() missing 1 required positional argument: 'self'" when I call CustomUser.get_first_name().
I checked my settings.py and do import CustomUser, models as well as settings in the view file.
If you could help me here that would be awesome.
models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(verbose_name='email', unique=True)
first_name = models.CharField(verbose_name='first_name', max_length = 15)
last_name = models.CharField(verbose_name='last_name', max_length = 15)
organization = models.CharField(verbose_name="organization", max_length = 15, choices=ORGANIZATIONS)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True) # check this for login email purposes
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'organization']
objects = CustomUserManager()
def get_full_name(self):
'''
Returns the first_name plus the last_name, with a space in between.
'''
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
'''
Returns the short name for the user.
'''
return self.first_name
def __str__(self):
return self.email
def get_organization(self):
return self.organization
def get_first_name(self):
return self.first_name
def get_email(self):
return self.email
views.py
class Dashboard(LoginRequiredMixin, TemplateView):
template_name = "plot.html"
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(Dashboard, self).get_context_data(**kwargs)
context['plot'] = plots.plotsurvey()
return context
plots.py
def plotsurvey():
c = CustomUser()
name = c.get_first_name()
df = pd.read_csv(str(name) +'.csv') #
trace = go.Bar(
x = df['Y'],
y = df['Z'], name = 'N'
)
data = [trace]
layout = go.Layout(title="X", margin = dict(b = 150))
fig = go.Figure(data=data, layout=layout)
plot_div = plot(fig, output_type='div', include_plotlyjs=False)
#logger.info("Plotting number of points {}.".format(3))
return plot_div
You are using an instance method, as if it were a class method.
You need to change, this
def plotsurvey():
c = CustomUser()
name = CustomUser.get_first_name()
...
To this (use the instance)
def plotsurvey():
c = CustomUser()
name = c.get_first_name()
...
Note that you have another problem here. You are not actually getting any real user with c = CustomUser(). To get a user, you would need to do something like
CustomUser.objects.get(pk=user_id)
In that case, you finally get:
def plotsurvey(user_id):
c = CustomUser.objects.get(pk=user_id)
name = c.get_first_name()
...
EDIT
We can be more practical, using the view.
class Dashboard(LoginRequiredMixin, TemplateView):
template_name = "plot.html"
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(Dashboard, self).get_context_data(**kwargs)
user = self.request.user
context['plot'] = plots.plotsurvey(user.pk)
return context
You can use request object
request.user.get_first_name()
I'm trying to make an editing page for the users to update an object data. However, form.is_valid() keeps failing, I have no idea why.
My model:
class Thread(models.Model):
title = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
body = models.TextField(max_length=10000)
USER_TYPES = (
('INI','Iniciante'),
('INT','Intermediário'),
('AVA','Avançado')
)
user_type = models.CharField(max_length=20, choices = USER_TYPES, default='INI')
category = models.ForeignKey(Category)
orcamento = models.IntegerField(default=0)
slug = models.SlugField(max_length=40, unique=True)
def get_absolute_url(self):
return "/%s/" % self.slug
def __str__(self):
return self.title
def save(self, **kwargs):
slug_str = "%s %s" % (self.category, self.title)
unique_slugify(self, slug_str)
super(Thread, self).save(**kwargs)
My view:
def edit_thread(request, thread_slug):
thread = Thread.objects.get(slug=thread_slug)
if request.method == 'POST':
form = EditThread(request.POST)
if form.is_valid():
thread.title = form.cleaned_data['title']
thread.orcamento = form.cleaned_data['orcamento']
thread.user_type = form.cleaned_data['experiencia']
thread.body = form.cleaned_data['pergunta']
thread.save()
return HttpResponseRedirect('/thread' + thread.get_absolute_url())
else:
data = {'title' : thread.title, 'experiencia':thread.user_type, 'orcamento' : thread.orcamento, 'pergunta': thread.body}
form = EditThread(initial=data)
return render(request, 'edit_thread.html', {
'form': form })
My form:
class EditThread(forms.ModelForm):
title = forms.CharField(label='Título', max_length=200, error_messages=my_default_errors)
orcamento = forms.IntegerField(label='Preço máximo', error_messages=my_default_errors)
experiencia = forms.ChoiceField(label='Você é um usuário...', choices=Thread.USER_TYPES, error_messages=my_default_errors)
pergunta = forms.CharField(label='Pergunta', widget=forms.Textarea, error_messages=my_default_errors)
class Meta:
model = Thread
def __init__(self, *args, **kwargs):
super(EditThread, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Div('title',
'experiencia',
PrependedAppendedText('orcamento', 'R$', ',00', active=True),
'pergunta',
FormActions(
Submit('save', 'Salvar alterações'),
)))
When accessing the page, the form gets pre-populated with the object's data as it should.
Your form should be inherited from the simple forms.Form instead of the forms.ModelForm:
class EditThread(forms.Form):
...
I would suggest you look at django's class based UpdateView. It can generate an update form for you or you could give it a custom ModelForm by overriding the form_class attribute on your view. When using a ModelForm, you also have to specify which model the form is for eg:
class EditThread(forms.ModelForm):
"field definitions ..."
class Meta:
model = Thread
fields = ['my_field_1', 'my_field_2']