Django ModelFieldChoice select passing value - python

Hi i'm using ModelFieldChoice to set the foreign key from Provider in the model "Article" (Article belongs to Provider). The select in the template is displayed correctly with all the providers from the database, but when i try to post the form, it throws an error that the select value is required even if i'm passing it. Also i seted values for the article in the database, and when i tried to edit it, all the fields in the form are populated with the correct data except for the select.
These are my models, i would appreciate the help, thanks! Sorry if i'm doing something wrong, this is my first time posting in stackoverflow.
Article.py Model
class Article(models.Model):
codigo = models.CharField(max_length=100, verbose_name='Codigo')
proveedor = models.ForeignKey(Provider, on_delete=models.CASCADE)
descripcion = models.CharField(max_length=200, verbose_name='Descripcion',null=False, blank=True)
marca = models.CharField(max_length=100, verbose_name='Marca',null=True, blank=True)
rubro = models.CharField(max_length=100, verbose_name='Rubro',null=True, blank=True)
nota = models.TextField(verbose_name='Nota',null=True)
costo = models.CharField(max_length=50, verbose_name='Costo',null=False, blank=True)
created = models.DateTimeField(auto_now_add=True, verbose_name="Fecha de creación",null=True, blank=True)
updated = models.DateTimeField(auto_now=True, verbose_name="Fecha de edición",null=True, blank=True)
class Meta:
verbose_name = "articulo"
verbose_name_plural = "articulos"
ordering = ['-descripcion']
def __str__(self):
return self.descripcion
Provider.py Model
class Provider(models.Model):
razon_social = models.CharField(max_length=100, verbose_name='Razón Social', unique=True)
direccion = models.CharField(max_length=100, verbose_name='Dirección', blank=True, null=True)
localidad = models.CharField(max_length=100, verbose_name='Localidad', blank=True, null=True)
provincia = models.CharField(max_length=100, verbose_name='Provincia', blank=True, null=True)
telefono = models.CharField(max_length=100, verbose_name='Teléfono', blank=True, null=True)
mail = models.CharField(max_length=100, verbose_name='Email', blank=True, null=True)
web = models.CharField(max_length=100, verbose_name='Sitio Web', blank=True, null=True)
created = models.DateTimeField(auto_now_add=True, verbose_name="Fecha de creación", null=True)
updated = models.DateTimeField(auto_now=True, verbose_name="Fecha de edición", null=True)
class Meta:
verbose_name = "proveedor"
verbose_name_plural = "proveedores"
ordering = ['-razon_social']
def __str__(self):
return self.razon_social
form.py (ArticleCreate)
class ArticleCreate(forms.ModelForm):
proveedor_id = forms.ModelChoiceField(queryset=Provider.objects.none(), empty_label="Elegir un proveedor")
class Meta:
model = Article
fields = '__all__'
def __init__(self, *args, **kwargs):
super(ArticleCreate, self).__init__(*args, **kwargs)
self.fields['proveedor_id'].queryset = Provider.objects.all()
views.py
def add_article(request):
if request.method == 'POST':
create = ArticleCreate(request.POST)
print(request.POST['proveedor_id'])
if create.is_valid():
create.save()
return redirect('/dashboard/articles/?add=success')
else:
print(create.errors)
return redirect('/dashboard/articles/?error=True')
else:
return render(request, "article/add_edit_article.html", {'editMode': False,'form': ArticleCreate})
In views.py when i print 'proveedor_id' the value is correctly displayed in console but then the "is_valid()" fails and it prints the error "<ul class="errorlist"><li>proveedor<ul class="errorlist"><li>Este campo es obligatorio.</li></ul></li></ul>" (obligatory field, as if i'm not passing it)

First, simplify your ArticleCreate serializer to be like this:
class ArticleCreate(forms.ModelForm):
class Meta:
model = Article
Then in the request pass proveedor field, not proveedor_id. In Django/DRF you should pass association IDs using "{{association_name}}": id pattern, not "{{association_name}}_id": id
Sou you can simplify your view as well:
def add_article(request):
if request.method == 'POST':
create = ArticleCreate(request.POST)
if create.is_valid():
create.save()
...

Related

How to make a table only visible to a specific user in Django

So, I was studying Django and started doing some projects to fixate what I learned.
I'm building a contact book like website and want to make each user have a unique Contacts table.
I've tried putting this on models.py:
class UserContatos(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
class Contato(models.Model):
nome = models.CharField(max_length=255)
sobrenome = models.CharField(max_length=255, blank=True)
telefone = models.CharField(max_length=255)
email = models.CharField(max_length=255, blank=True)
data_criacao = models.DateTimeField(
default=timezone.now)
descricao = models.TextField(blank=True)
categoria = models.ForeignKey(Categoria, on_delete=models.DO_NOTHING)
mostrar = models.BooleanField(default=True)
foto = models.ImageField(blank=True, upload_to='fotos/%y/%m/%d')
def __str__(self):
return self.nome
contatos = Contato()
class ContatoForm(forms.ModelForm):
class Meta:
model = UserContatos.Contato
exclude = ('',)
When I use this form to create a contact, it doesn't "go to the user".

Populate a Django form field with data from a model

I'm have been struggling on this for 2 days, really. I want to populate Timesheet form field from Employees model as a select field / dropdown list.
Here are my files and I tried so far.
MODEL.PY
class Employees(models.Model):
# MONTHLY = 'MONTHLY'
# SEMIMONTHLY = 'SEMIMONTHLY'
# BIWKEEKLY = 'BIWKEEKLY'
# WEEKLY = 'WEEKLY'
# DAILY = 'DAILY'
PAY_PERIODS = [
('Monthly', 'Monthly'),
('Bi-weekly', 'Bi-weekly'),
('Weekly', 'Weekly'),
('Daily', 'Daily'),
]
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
is_active = models.BooleanField(default=True, verbose_name='Employee is actives')
first_name = models.CharField(max_length=50, verbose_name='First Name.', null=True, blank=False)
middle_name = models.CharField(max_length=50, verbose_name='Middle Name or Initials.', null=True, blank=True)
last_name = models.CharField(max_length=50, verbose_name='Last Name.', null=True, blank=False)
full_name = models.CharField(max_length=50, null=True, blank=True)
phone = PhoneField(blank=True, null=True)
email = models.EmailField(max_length=150, blank=True, null=True)
state = USStateField(null=True, blank=True)
street_address = models.CharField(max_length=150, blank=True, null=True, verbose_name='Street Address.')
zip_code = models.CharField(max_length=50, blank=True, null=True, verbose_name='Zip Code.')
hourly_rate = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
pay_frequency = models.CharField(max_length=100, choices=PAY_PERIODS, blank=True)
hire_date = models.TimeField(auto_now_add=True)
def __str__(self):
return self.full_name
def save( self, *args, **kwargs ):
self.full_name = f'{self.first_name} {self.middle_name} {self.last_name}'
super().save( *args, **kwargs )
class Timesheet(models.Model):
"""A timesheet is used to collet the clock-ins/outs for a particular day
"""
employer = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
full_name = models.ForeignKey(Employees, on_delete=models.CASCADE, null=True, blank=False, verbose_name='Select YOUR Name')
start_date = models.DateField(auto_now_add=True, null=True)
end_date = models.DateField(null=True, blank=False)
time_worked = models.DateField(null=True, blank=False)
def __str__(self):
return self.full_name
VIEWS.PY # I tried both function and class based views
class TimesheetView(CreateView):
model = Timesheet
fields = ('full_name', )
# form_class = TimesheetFrom
# queryset = Employees.objects.filter()
# print(queryset)
template_name = 'users/timesheet.html'
success_url = reverse_lazy('timesheet')
#login_required
def timesheet_view(request):
if request.method == 'POST':
form = TimesheetFrom(request.POST)
if form.is_valid():
emp = form.save(commit=False)
emp.user_id = request.user.pk
emp.save()
return redirect('dashboard')
else:
form = TimesheetFrom()
context = {
'form': TimesheetFrom(),
}
return render(request, 'users/timesheet.html', context)
FORM.PY
class TimesheetFrom(forms.Form):
class Meta:
model = Timesheet
fields = '__all__'
exclude = ('employer', )
#This is the current state of the form but I did tried many approaches.
I did search extensively here (Stackoverflow) but no use case for me. Any help will be greatly appreciated with a cup of coffee.

Django : RelatedObjectDoesNotExist in view but works fine in Admin

I am getting a (RelatedObjectDoesNotExist: UserProfile has no site) error in one of my views yet I am able to perform all CRUD operations in the admin with out any errors.
django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist: UserProfile has no site.
Excerpt from models.py
class Sites(models.Model):
name = models.CharField(max_length=255, blank=True, null=True)
active = models.NullBooleanField()
created_at = models.DateTimeField(blank=True, null=True)
updated_at = models.DateTimeField(blank=True, null=True)
logo_file_name = models.CharField(max_length=255, blank=True, null=True)
logo_content_type = models.CharField(max_length=255, blank=True, null=True)
logo_file_size = models.IntegerField(blank=True, null=True)
logo_updated_at = models.DateTimeField(blank=True, null=True)
logo_path = models.CharField(max_length=255, blank=True, null=True)
account_type = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
site_str = 'id = {}, name = {}'.format(self.id, self.name)
return site_str
class Meta:
managed = True
db_table = 'sites'
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
site = models.ForeignKey(Sites)
def __str__(self):
user_profile_str = '{}: {}'.format(self.user.username, str(self.site))
return user_profile_str
Excerpt form views.py
#login_required
def client_list(request):
user_profile = UserProfile(user=request.user)
print(user_profile.user.username)
clients = Clients.objects.filter(site_rec=user_profile.site)
return render(request, 'snapreport/clients/all_clients.html', {'clients': clients})
In this line: user_profile = UserProfile(user=request.user) you're creating a new UserProfile for the user. And since you don't assign it a site, user_profile.site is None (or trying to access it throws RelatedObjectDoesNotExist).
You probably want:
user_profile = UserProfile.objects.get(user=request.user)
if the profile already exists (assuming that will have a site).

Include other field as choices to foreign key, Django

I have two models as follows :
class FlightSchedule(models.Model):
tail_number = models.ForeignKey(TailNumber, null=False, blank=False)
flight_number = models.CharField(max_length=30, null=False, blank=False)
flight_group_code = models.ForeignKey(FlightGroup, null=False, blank=False)
origin_port_code = models.ForeignKey(Port, null=False, related_name="Origin", blank=False)
destination_port_code = models.ForeignKey(Port, null=False, related_name="Destination", blank=False)
flight_departure_time = models.TimeField()
start_date = models.DateField()
end_date = models.DateField()
def __unicode__(self):
return u'%s' % self.flight_number
class Meta:
verbose_name_plural = "flights Schedule"
class PosFlightSchedule(models.Model):
tail_number = models.ForeignKey(TailNumber, null=False, blank=False)
pos_flight_number = models.ForeignKey(FlightSchedule, max_length=30, null=False, blank=False,
related_name='pos_flight_number')
pos_flight_departure_time = models.ForeignKey(FlightSchedule, max_length=30,
related_name='pos_flight_departure_time')
pos_route_id = models.ForeignKey(FlightScheduleDetail, null=False, blank=False, related_name='pos_route_id')
pos_flight_date = models.ForeignKey(FlightScheduleDetail, null=False, blank=False, related_name='pos_flight_date')
pax_count = models.IntegerField(null=True)
def __unicode__(self):
return u'%s' % self.pos_flight_number
class Meta:
verbose_name_plural = "Flights Schedule"
For the pos_flight_departure_time , I need the choices from flight_departure_time from the FlightSchedule class. But I get the flight_number values in the drop down. What do I have to change, to get the flight_departure_time values? The classes are from different apps in a single django project. So they have two admin files.
No you don't actually need that. You need only one foreign key in your second model to FlightScheduleDetail and you need just one foreign key to FlightSchedule
class PosFlightSchedule(models.Model):
tail_number = models.ForeignKey(TailNumber, null=False, blank=False)
flight = models.ForeignKey(FlightSchedule, null=False, blank=False,related_name='pos_flight_number')
related_name='pos_flight_departure_time')
pos_route_id = models.ForeignKey(FlightScheduleDetail, null=False, blank=False, related_name='pos_route_id')
pax_count = models.IntegerField(null=True)
def __unicode__(self):
return u'%s' % self.pos_flight_number
class Meta:
verbose_name_plural = "Flights Schedule"
Then all the fields declared in the first model automatically become available to PosFlightSchedule
So for example you can do
p = PosFlightSchedule.objects.all()[0]
print (p.flight.flight_number)
print (p.flight.pos_flight_departure_time)
etc.
This is the correct way to do it.
You may solve this by defining model form, and by not changing to models.py
class PosFlightScheduleForm(forms.ModelForm):
pos_flight_departure_time = forms.ChoiceField(label="Pos Department Time",
choices=[(i.pk, i.flight_departure_time) for i in FlightSchedule.objects.all()],
required=True)
def __init__(self, *args, **kwargs):
super(PosFlightScheduleForm, self).__init__(*args, **kwargs)
self.fields['pos_flight_departure_time'] = forms.ChoiceField(label="Pos Department Time",
choices=[(i.pk, i.flight_departure_time) for i in FlightSchedule.objects.all()],
required=False)
class Meta:
model = PosFlightSchedule
fields = (
"tail_number", 'pos_flight_departure_time',)
In view.py You may use this form
def add_view(self, request):
form = PosFlightScheduleForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('/postflights')
context = {
'form': form,
}
return render(request, 'path/form.html', context)

Testing Django Inline ModelForms: How to arrange POST data?

I have a Django 'add business' view which adds a new business with an inline 'business_contact' form.
The form works fine, but I'm wondering how to write up the unit test - specifically, the 'postdata' to send to self.client.post(settings.BUSINESS_ADD_URL, postdata)
I've inspected the fields in my browser and tried adding post data with corresponding names, but I still get a 'ManagementForm data is missing or has been tampered with' error when run.
Anyone know of any resources for figuring out how to post inline data?
Relevant models, views & forms below if it helps. Lotsa thanks.
MODEL:
class Contact(models.Model):
""" Contact details for the representatives of each business """
first_name = models.CharField(max_length=200)
surname = models.CharField(max_length=200)
business = models.ForeignKey('Business')
slug = models.SlugField(max_length=150, unique=True, help_text=settings.SLUG_HELPER_TEXT)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
phone = models.CharField(max_length=100, null=True, blank=True)
mobile_phone = models.CharField(max_length=100, null=True, blank=True)
email = models.EmailField(null=True)
deleted = models.BooleanField(default=False)
class Meta:
db_table='business_contact'
def __unicode__(self):
return '%s %s' % (self.first_name, self.surname)
#models.permalink
def get_absolute_url(self):
return('business_contact', (), {'contact_slug': self.slug })
class Business(models.Model):
""" The business clients who you are selling products/services to """
business = models.CharField(max_length=255, unique=True)
slug = models.SlugField(max_length=100, unique=True, help_text=settings.SLUG_HELPER_TEXT)
description = models.TextField(null=True, blank=True)
primary_contact = models.ForeignKey('Contact', null=True, blank=True, related_name='primary_contact')
business_type = models.ForeignKey('BusinessType')
deleted = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
address_1 = models.CharField(max_length=255, null=True, blank=True)
address_2 = models.CharField(max_length=255, null=True, blank=True)
suburb = models.CharField(max_length=255, null=True, blank=True)
city = models.CharField(max_length=255, null=True, blank=True)
state = models.CharField(max_length=255, null=True, blank=True)
country = models.CharField(max_length=255, null=True, blank=True)
phone = models.CharField(max_length=40, null=True, blank=True)
website = models.URLField(null=True, blank=True)
class Meta:
db_table = 'business'
def __unicode__(self):
return self.business
def get_absolute_url(self):
return '%s%s/' % (settings.BUSINESS_URL, self.slug)
VIEWS:
def business_add(request):
template_name = 'business/business_add.html'
if request.method == 'POST':
form = AddBusinessForm(request.POST)
if form.is_valid():
business = form.save(commit=False)
contact_formset = AddBusinessFormSet(request.POST, instance=business)
if contact_formset.is_valid():
business.save()
contact_formset.save()
contact = Contact.objects.get(id=business.id)
business.primary_contact = contact
business.save()
#return HttpResponse(help(contact))
#business.primary = contact.id
return HttpResponseRedirect(settings.BUSINESS_URL)
else:
contact_formset = AddBusinessFormSet(request.POST)
else:
form = AddBusinessForm()
contact_formset = AddBusinessFormSet(instance=Business())
return render_to_response(
template_name,
{
'form': form,
'contact_formset': contact_formset,
},
context_instance=RequestContext(request)
)
FORMS:
class AddBusinessForm(ModelForm):
class Meta:
model = Business
exclude = ['deleted','primary_contact',]
class ContactForm(ModelForm):
class Meta:
model = Contact
exclude = ['deleted',]
AddBusinessFormSet = inlineformset_factory(Business,
Contact,
can_delete=False,
extra=1,
form=AddBusinessForm,
)
The problem is you have not included the management form in your data. You need to include form-TOTAL_FORMS (total number of forms in the formset, default is 2), form-INITIAL_FORMS (the initial number of forms in the formset, default is 0) and form-MAX_NUM_FORMS (the maximum number of forms in the formset, default is '').
See the Formset documentation for more information on the management form.

Categories