How to add default value in queryset? - django

I have a moneybook, moneylog models
and moneylog get relation with moneybook manytomany.
moneybook = models.ForeignKey(
moneybook_models.Moneybook, on_delete=models.CASCADE)
pay_day = models.DateTimeField(default=NOW)
payer = models.ForeignKey(
user_models.User, on_delete=models.CASCADE, related_name="payer")
dutch_payer = models.ManyToManyField(
user_models.User, related_name="dutch_payer", blank=True)
price = models.IntegerField()
category = models.CharField(max_length=10)
memo = models.TextField()
I want payer default save in dutch_payer if user choose or not.
and this is my forms.py
class CreateMoneylogForm(forms.ModelForm):
class Meta:
model = models.Moneylog
fields = (
"pay_day",
"payer",
"dutch_payer",
"price",
"category",
"memo",
)
widgets = {
"dutch_payer": forms.CheckboxSelectMultiple
}
def save(self, *args, **kwargs):
moneylog = super().save(commit=False)
return moneylog
views.py
class moneylog_create(FormView):
form_class = forms.CreateMoneylogForm
template_name = "moneylogs/create.html"
def form_valid(self, form):
moneylog = form.save()
moneybook = moneybook_models.Moneybook.objects.get(
pk=self.kwargs["pk"])
form.instance.moneybook = moneybook
if moneylog.payer not in moneylog.dutch_payer.all():
moneylog.dutch_payer.add(moneylog.payer)
moneylog.save()
form.save_m2m()
return redirect(reverse("cores:home"))
as you see.
if moneylog.payer not in moneylog.dutch_payer.all():
moneylog.dutch_payer.add(moneylog.payer)
moneylog.save()
form.save_m2m()
return redirect(reverse("cores:home"))
this not work.(there is no payer in dutch_payer) how can i achieve it?

Related

Django UpdateView Two Seperate Form Save (included inlineformset_factory)

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.

error datefiled input when add new record

I have next problem.
I have models: Period and CompletedWork
class Period(models.Model):
date = models.DateField()
def __repr__(self):
return self.date
class CompletedWork(models.Model):
period = models.ForeignKey(directory.Period,
on_delete=models.SET('deleted date'),
)
worker = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET('deleted worker'),
related_name='worker_do', default=settings.AUTH_USER_MODEL
)
work_done = models.ForeignKey(directory.WorksType, on_delete=models.SET('deleted works type'))
work_scope = models.FloatField(blank=True, null=True)
work_notes = models.CharField(_("Comments"), max_length=70, blank=True, null=True, )
record_author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET('deleted user'),
related_name='record_author', auto_created=True,
)
record_date = models.DateTimeField(auto_now=True)
checked_by_head = models.BooleanField(default=False)
active = models.BooleanField(default=True)
def __repr__(self):
return f'{self.period}, {self.worker}, {self.work_done}'
def __str__(self):
return self.__repr__()
def is_active(self):
if self.active:
return True
return False
def __str__(self):
return str(self.__repr__())
In the forms I make a widget for Date input:
class CompletedWorkForm(forms.ModelForm):
class Meta:
model = CompletedWork
fields = (
'period',
'worker',
'work_done',
'work_scope',
'work_notes',
)
widgets = {
'period': DatePickerInput(),
}
widget.py looks like this:
class DatePickerInput(forms.DateInput):
input_type = 'date'
my view:
class CreateCompletedWorkView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
model = CompletedWork
form_class = CompletedWorkForm
template_name = 'completed_work_add.html'
success_url = reverse_lazy('completed_work_list')
success_message = f'Record successfully added'
def get_form_kwargs(self):
kwargs = super(CreateCompletedWorkView, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
def form_valid(self, form):
form.instance.record_author = self.request.user
return super().form_valid(form)
And now I have a problem creating a new record:
"Select a valid choice. That choice is not one of the available choices."
Please tell me how can I fixed. I understand, that maybe problem with the format that I get after POST

Convert function base view to class based view (DRF)

can someone help me convert this function component to class based view (rest framework concrete view)?
I tried converting but landed with errors where serializer is false.
Product image is required in the query.
class Product(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
stock = models.IntegerField()
is_available = models.BooleanField(default=True)
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
class ProductImage(models.Model):
image = models.ImageField(upload_to=get_upload_path)
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="product_images")
def store(request, category_slug):
cat = None
products = None
if category_slug != None:
cat = get_object_or_404(Category, slug=category_slug)
products = Product.objects.filter(category=cat)
product_count = products.count()
else:
products = Product.objects.filter(is_available=True)
products.count()
context = {
'products': products,
'product_count': product_count
}
return render(request, 'store.html', context)
what i tried with rest framework.
Serializers:
class ProductImageSerializer(serializers.ModelSerializer):
class Meta: model = ProductImage
fields = ('image',)
class ProductSerializer(serializers.ModelSerializer):
product_images = ProductImageSerializer(many=True, read_only=True)
class Meta:
model = Product
fields = "__all__"
def create(self, validated_data):
profile_data = validated_data.pop('product_images')
product = Product.objects.create(**validated_data)
return product
View:
I tried with concrete views, product is filtered by category.
class Store(generics.ListCreateAPIView):
queryset = Product.objects.filter(is_available=True)
serializer_class = ProductSerializer
lookup_field = 'category_slug'
lookup_url_kwarg = 'category_slug'
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
cat_slug = self.kwargs.get('category_slug')
products = None
if cat_slug is not None:
category = get_object_or_404(Category, slug=cat_slug)
products = queryset.filter(category=category, is_available=True)
else:
products = queryset.filter(is_available=True)
if products.count() == 1:
serializer = ProductSerializer(data=products.first())
elif products.count() > 1:
serializer = ProductSerializer(data=products, many=True)
if not serializer.is_valid():
print(serializer.errors)
data = serializer.data
return Response(data, status=status.HTTP_200_OK)
any help is appreciated.

how to return several FileField from Queryset in Django?

I have a models with FileField for videos.
When i upload only one video i can return it with this code in the view.py:
def cours(request, id, slug):
c = Cours.objects.get(id=id, slug=slug)
p = Plan_simple.objects.get(cours=c)
return render(request, 'upload/cours.html', locals())
But when i upload two or more videos whith formset, and i change get fuction by filter it doesn't work:
def cours(request, id, slug):
c = Cours.objects.get(id=id, slug=slug)
p = Plan_simple.objects.filter(cours=c)
return render(request, 'upload/cours.html', locals())
the models.py
class Cours(models.Model):
titre = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)
auteur = models.CharField(max_length=42)
comment = models.TextField(null=True)
link = models.CharField(max_length=100)
date = models.DateTimeField(default=timezone.now, verbose_name="Date de parution")
categorie = models.ForeignKey('Categorie', on_delete=models.CASCADE)
def save(self, *args, **kwargs):
self.slug = slugify(self.titre)
super(Cours, self).save(*args, **kwargs)
class Meta:
verbose_name = "cours"
db_table = "cours"
ordering = ['date']
class Plan_simple(models.Model):
partie = models.CharField(blank=True, max_length=100)
date = models.DateTimeField(default=timezone.now, verbose_name="Date de parution")
vid = models.FileField(upload_to='file/', blank=True, null = True)
cours = models.ForeignKey(Cours, related_name = "plan_simple", on_delete=models.CASCADE)
def __str__(self):
return self.partie
class Meta:
db_table = "plan_simple"
Can you help me?
Thanks
The issue is with this line. It does not request anything from the database. It only specifies a filter.
p = Plan_simple.objects.filter(cours=c)
You should change it to this...
p = Plan_simple.objects.filter(cours=c).all()

FormView is not showing validation errors

My model.py looks:
class VehicleInquiry(TimeStampedModel):
inquiry_status = models.PositiveSmallIntegerField(_("inquiry status"), choices=INQUIRY_STATUS_CHOICES, default=1)
ip = models.GenericIPAddressField(_("IP"), blank=True, null=True)
full_name = models.CharField(_("full name"), max_length=100)
address = models.CharField(_("address"), max_length=200)
phone_code = models.PositiveSmallIntegerField(_("phone code")
)
phone = models.CharField(_("phone"), max_length=20)
email = models.EmailField(_("email"))
is_subscribed = models.BooleanField(_("subscribed"), default=True)
vehicle = models.ForeignKey(VehicleStock, on_delete=models.SET_NULL, blank=True, null=True,
related_name="inquiries", verbose_name=_("vehicle")
)
country = models.ForeignKey(Country, on_delete=models.SET_NULL, blank=True, null=True,
related_name="inquiries", verbose_name=_("country")
)
arrival_port = models.ForeignKey(CountryPorts, on_delete=models.SET_NULL, blank=True, null=True,
related_name="inquiries", verbose_name=_("arrival port")
)
current_price = models.PositiveIntegerField(_('current price'), null=True, blank=True)
inspection = models.BooleanField(_("pre-export inspection"), default=False)
insurance = models.BooleanField(_("insurance"), default=True)
total = models.PositiveIntegerField(_('total price'), null=True, blank=True)
my form.py:
class VehicleInquiryForm(forms.ModelForm):
country2 = forms.TypedChoiceField(
label=_("Country"),
choices=[('','Arrival Country')]+[(country.id, country.name) for country in Country.objects.all().filter(visible=True).order_by('name')],
required=True,
)
phone_code = ChoiceFieldWithTitles(
label=_("Country dialing code"),
choices=[('','Dailing Code', 'Dailing Code')]+[(country.id, '{} (+{})'.format(country.name, country.phone_code), '+{}'.format(country.phone_code)) for country in Country.objects.all().filter(visible=True).order_by('name')],
required=True,
)
arrival_port = forms.TypedChoiceField(
label=False,
widget=forms.RadioSelect
)
phone = forms.CharField(
label=_("Phone"),
max_length=20,
required=True,
validators=[phone_number_validator]
)
full_name = StrippedCharField(
label=_("Full name"),
max_length=30,
required=True,
validators=[full_name_validator]
)
address = StrippedCharField(
label=_("Address"),
max_length=200,
required=True
)
class Meta:
model = VehicleInquiry
exclude = ('inquiry_status', 'vehicle', 'current_price', 'total')
def clean_country2(self):
country_id = self.cleaned_data['country2']
try:
country = Country.objects.get(id=country_id)
except Country.DoesNotExist:
raise forms.ValidationError(_('Please select the country'))
return country_id
def clean(self):
cleaned_data = super(VehicleInquiryForm, self).clean()
dialing_code = cleaned_data['phone_code']
try:
dialing_country = Country.objects.get(id=dialing_code)
except Country.DoesNotExist:
raise forms.ValidationError(_('Please select the phone code'))
return self.cleaned_data
def __init__(self, *args, **kwargs):
dialing_code = kwargs.pop('phone_code', None)
super(VehicleInquiryForm, self).__init__(*args, **kwargs)
self.fields['is_subscribed'].label = _("Keep me updated with news, specials offers and more.")
self.helper = FormHelper()
self.helper.template_pack = "bootstrap3"
self.helper.form_method = "post"
self.helper.form_id = "vehicle-shipping-form"
self.helper.form_show_errors = True
self.initial['insurance'] = True
self.fields['phone_code'].initial = dialing_code
self.helper.add_input(
Submit('inquiry', _('Inquiry'), css_class='btn btn-default',)
)
self.helper.form_method = 'post'
self.helper.layout = Layout(
Fieldset(
_("1. Choose Your Final Destination"),
Div(
Field('country2', css_class="order-select-country"),
),
-- other fields --
)
view.py
class VehicleStockDetailView(FormView):
template_name = "site/product/vehicle-detail.html"
template_name_done = "site/contact/contact-us-done.html"
template_name_done_email = "site/contact/emails/contact-us-done.html"
form_class = VehicleInquiryForm
model = VehicleStock
def get(self, request, slug, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
vehicle = get_object_or_404(VehicleStock, slug=slug)
similar_vehicles = VehicleStock.objects.get_public_available().filter(model__id=vehicle.model.id).exclude(slug=slug)[:6]
page_title = vehicle.model
return render(request, self.template_name, {'page_title': page_title, 'similar_products': similar_vehicles, 'stock_product': vehicle, 'shipping_form': form})
def post(self, request, slug, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
vehicle = get_object_or_404(VehicleStock, slug=slug)
similar_vehicles = VehicleStock.objects.get_public_available().filter(model__id=vehicle.model.id).exclude(slug=slug)[:6]
page_title = vehicle.model
if form.is_valid():
form.save()
return render(self.request, self.template_name_done, {'full_name': request.POST['full_name'], 'email': request.POST['email']})
return render(self.request, self.template_name, {'page_title': page_title, 'similar_products': similar_vehicles, 'stock_product': vehicle, 'shipping_form': form})
url.py
url(r'^vehicle/(?P<slug>[-_\w]+)/$', VehicleStockDetailView.as_view(), name='vehicle-detail'),
Now, when I fill the form and send inquiry it is not showing any error but showing again the form with entered field values except phone_code (it is showing default value). No errors showing, but the form is not validated. I tried different ways with TemplateView and with FormView. But no success.Deadly need any help.
You haven't passed the POSTed data to the form anywhere.
This is one of the reasons why you should not be overriding the get and post methods. The point of the various class-based views is that they do almost all of this for you. You should be inheriting from CreateView, so that the form is saved when it is valid, and the extra logic you have added should be in get_context_data - as you can see, this avoids having to include the same code twice.
class VehicleStockDetailView(CreateView):
template_name = "site/product/vehicle-detail.html"
template_name_done = "site/contact/contact-us-done.html"
template_name_done_email = "site/contact/emails/contact-us-done.html"
form_class = VehicleInquiryForm
model = VehicleStock
def get_context_data(self, *args, **kwargs):
context = super(VehicleStockDetailView, self).get_context_data(*args, **kwargs)
context['vehicle'] = get_object_or_404(VehicleStock, slug=self.kwargs['slug'])
context['similar_vehicles'] = VehicleStock.objects.get_public_available().filter(model__id=vehicle.model.id).exclude(slug=slug)[:6]
context['page_title'] = vehicle.model
return context
def form_valid(self, form, *args, **kwargs):
obj = form.save()
return render(self.request, self.template_name_done, {'full_name': self.request.POST['full_name'], 'email': self.request.POST['email']})
Note also that you really should never directly render a template on success; you should always redirect. Again, the form view takes care of this for you.