Populate a Django form field with data from a model - python

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.

Related

Cannot assign "'Sample Category'": "Product.category" must be a "Category" instance

While creating new products I'm getting such kind of error. Can someone help me?
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name_geo = models.CharField(max_length=200, null=True, blank=True)
image = models.ImageField(null=True, blank=True, default='/placeholder.png')
brand = models.CharField(max_length=200, null=True, blank=True)
category = models.ForeignKey(Category, null=False, default=0, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
countInStock = models.IntegerField(null=True, blank=True, default=0)
createdAt = models.DateTimeField(auto_now_add=True)
_id = models.AutoField(primary_key=True, editable=False)
def __str__(self):
return self.name_geo
class Category(models.Model):
_id = models.AutoField(primary_key=True, editable=False)
name = models.CharField(max_length=200, null=True, blank=True)
createdAt = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
#api_view(['POST'])
def createProduct(request):
user = request.user
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category="Sample Category",
price=0,
brand='Sample Brand',
countInStock=0,
)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
Without separating category class in models.py everything works fine. I mean If i didn't use ForeignKey in Products class for category
It just has to be a Category Instance/Object
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category=Category.objects.get_or_create(name="Sample Category"),
price=0,
brand='Sample Brand',
countInStock=0,
)
Notes:
You could just do a .get() or a .filter().first() if you don't want to create
If you use a form, you can get away with just the Category's PK/_id in the POST
this type of thing: f = form(request.POST) f.is_valid() f.save()
At the end that field will hold the PK/_id/Row# of the Category Obj

Initial data not working if I hide some one-to-many fields in django

I want to prefill some one to many fields and also hide these field because I want to avoid a scenario where a user can see all the records related to the fields. The problem I'm facing is when I use 'all' on the form fields I the initial data dictionary is working well, but if I try to use a list of the fields I want displayed, the initial data is not getting passed into the form.
Here is my models.py:
class Agent(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = OneToOneField(User, null=True, blank=True, on_delete=models.SET_NULL)
first_name = models.CharField(max_length=15, null=True, blank=True,)
surname = models.CharField(max_length=15, null=True, blank=True,)
provcoord = models.ForeignKey(Provcoord, null=True, blank=True, on_delete=SET_NULL)
regcoord = models.ForeignKey(Regcoord, null=True, blank=False, on_delete=SET_NULL)
region = models.CharField(max_length=15, null=False, blank=True, choices=REGION)
province = models.CharField(max_length=15, null=False, blank=False, choices=PROVINCE)
id_no = id_no = models.CharField(max_length=10, null=False, blank=False, unique=True,)
agent_no = models.CharField(default="Not Assigned", max_length=20, null=False, blank=False)
address = models.TextField(null=False, blank=False)
gender = models.CharField(max_length=20, null=False, blank=False, choices=GENDER)
profile_pic = models.ImageField(upload_to="assets", default="default.png")
is_blacklisted = models.BooleanField(default=False)
reason_for_blacklist = models.TextField(max_length=500, null=True, blank=True)
registered_at = models.DateTimeField(auto_now_add=True)
def get_absolute_url(self):
return reverse("agent", kwargs={'str' :str.id})
def __str__(self):
return self.user.username
class Adult(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
agent = models.ForeignKey(Agent, null=True, blank=True, on_delete=SET_NULL)
regcoord = models.ForeignKey(Regcoord, null=True, blank=True, on_delete=SET_NULL)
provcoord = models.ForeignKey(Provcoord, null=True, blank=True, on_delete=SET_NULL)
surname = models.CharField(max_length=150, null=False, blank=False)
first_name = models.CharField(max_length=150, null=False, blank=False)
other_name = models.CharField(max_length=150, null=True, blank=True)
address = models.CharField(max_length=200, null=True, blank=True)
region = models.CharField(max_length=15, null=True, blank=True,choices=PROVINCE)
dob = models.CharField(max_length=10, null=False, blank=False)
gender = models.CharField(max_length=20, null=False, blank=False, choices=GENDER)
id_no = models.CharField(max_length=12, null=False, blank=False, unique=True)
receipt_no = models.CharField(max_length=10, default="Not Receipted", null=True,
blank=True)
phone_no = models.CharField(max_length=20, null=False, blank=False,)
marital_status = models.CharField(max_length=20, null=False, blank=False, choices=MARITAL_STATUS)
views.py:
def add_parent(request,):
agent = request.user.agent
regcoord = request.user.agent.regcoord
provcoord = request.user.agent.provcoord
region = request.user.agent.region
province = request.user.agent.province
form = ParentForm(initial={
'agent' :agent,
'regcoord' :regcoord,
'provcoord' :provcoord,
'region' :region,
'province' :province
})
if request.method == 'POST':
form = ParentForm(request.POST, request.FILES,)
if form.is_valid():
form.save()
return redirect('/')
context = {'form' :form}
return render(request, 'kyc/add_adult.html', context)
forms.py:
class ParentForm(ModelForm):
class Meta:
model = Adult
fields = ['surname',
'first_name',
'other_name',
'address',
'dob',
'gender',
'id_no',
'receipt_no',
'phone_no',
'image'
]
Please Help on how I can get around this issue.
Here is an approach I suggest (not tested though):
from django import forms
class ParentForm(ModelForm):
agent = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
regcoord = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
provcoord = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
region = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
province = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(ParentForm, self).__init__(*args, **kwargs)
self.fields['agent'].initial = self.user.agent
self.fields['regcoord'].initial = self.user.regcoord
self.fields['provcoord'].initial = self.user.provcoord
self.fields['region'].initial = self.user.region
self.fields['province'].initial = self.user.province
class Meta:
model = Adult
fields = ['surname',
'first_name',
'other_name',
'address',
'dob',
'gender',
'id_no',
'receipt_no',
'phone_no',
'image'
]
Notes how I referenced the 5 fields (agent, regcoord, provcoord, region, province) as extra fields by declaring them as simple CharFields. So they are no longer rendered from the model as dropdown lists. Then in the method __init__ I define the initial values ​​for each of the fields.
Your function add_parent should become:
def add_parent(request,):
form = ParentForm(user=request.user)
if request.method == 'POST':
form = ParentForm(request.POST, request.FILES,)
if form.is_valid():
form.save()
return redirect('/')
context = {'form' :form}
return render(request, 'kyc/add_adult.html', context)
Edit
Here is another alternative:
def add_parent(request,):
data = {'agent': request.user.agent, 'regcoord': request.user.regcoord, 'provcoord': request.user.provcoord, 'region': request.user.region, 'province': request.user.province}
form = ParentForm(initial=data)
if request.method == 'POST':
form = ParentForm(request.POST, request.FILES,)
if form.is_valid():
form.save()
return redirect('/')
context = {'form' :form}
return render(request, 'kyc/add_adult.html', context)
In the function add_parent, I pass the initial values ​​in the form of a dictionary (data), to the variable initial.
Then you need to remove the __init__ method from your form. Django will take care of rendering the form with the initial values ​​in the corresponding fields.

How To Hide Form Fields When A Particular Type Of Product Is Selected Django

Please I have a project where I want to hide some fields in a form when the category selected belongs to a particular product type. The type of products is Single and Bundle products. So for instance, if I choose something like pens(Bundle) in the form category I should only see quantity in the form fields but if I select something like Desk(single) all fields should be available to fill. How do I implement this in Django? Thank you
My Model
TYPE =(('Single', 'Single'),('Bundle','Bundle'))
class Category(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
pro_type = models.CharField(max_length=50, choices=TYPE, null=True)
timestamp = models.DateTimeField(auto_now_add=False, auto_now=True, null=True)
def __str__(self):
return f'{self.name}'
class Product(models.Model):
pro_name = models.CharField(max_length=100, blank=True, null=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True, null=True)
quantity = models.IntegerField(default='0', blank=True, null=True)
issue_to = models.ForeignKey('Order',default='', on_delete=models.CASCADE,blank=True, null=True)
serial_num = models.CharField(max_length=100, blank=True, null=True)
model_num = models.CharField(max_length=100, blank=True, null=True)
storage_size = models.CharField(max_length=50, blank=True, null=True)
My views
def add_products(request):
form = ProductCreateForm(request.POST)
if request.method == 'POST':
if form.is_valid():
obj = form.save(commit=False)
obj.staff = request.user
obj.save()
return redirect('dashboard-products')
else:
form = ProductCreateForm()
context = {
'form': form,
}

Django: get the max count of a foreign key based on other foreign key

I have this Model:
class Complaint(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
name = models.CharField(max_length=255, unique=True)
definition = models.TextField(blank=False, default="")
is_violent = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
class Meta:
ordering = ['name']
def get_absolute_url(self):
return reverse('complaint-details', kwargs={'pk': self.pk})
class Service(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
name = models.CharField(max_length=255, unique=True)
definition = models.TextField(blank=True, default="")
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('service-details', kwargs={'pk': self.pk})
class Location(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
location_name = models.CharField(max_length=255, unique=True)
loc_lat = models.DecimalField(max_digits=9, decimal_places=6)
loc_long = models.DecimalField(max_digits=9, decimal_places=6)
pop = models.PositiveIntegerField(default=500)
is_AOR = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.location_name
class Blotter(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)#default=timezone.now().date()
date = models.DateField(blank=True)
time = models.TimeField(blank=True)
entry_number = models.CharField(max_length=255, unique=True,validators=[RegexValidator(r'^\d{1,255}$')])
complaints = models.ForeignKey(Complaint, on_delete=models.CASCADE, null=True, blank=True)
service = models.ForeignKey(Service, on_delete=models.CASCADE, null=True, blank=True)
information = models.TextField(blank=False, default="")
location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True, blank=True)
is_active = models.BooleanField(default=True)
class Meta:
ordering = ("date_created",)
def __str__(self):
return (self.entry_number)
def get_absolute_url(self):
return reverse('details-blotter', kwargs={'pk': self.pk})
And I have this serializer:
class APILocationListSerializer(serializers.Serializer):
address = serializers.CharField()
latitude = serializers.DecimalField(max_digits=9, decimal_places=5)
longitude = serializers.DecimalField(max_digits=9, decimal_places=5)
population= serializers.IntegerField()
crime_count=serializers.IntegerField()
crime_rate=serializers.DecimalField(max_digits=4, decimal_places=3)
is_aor = serializers.BooleanField()
class Meta:
model = Blotter
fields= [
'address',
'latitude',
'longitude',
'population',
'crime_count',
'crime_rate'
'is_aor',
]
def to_representation(self, value):
context = {
value['address']:
{
'coordinates':[value['latitude'],value['longitude']],
'Population': value['population'],
'Crime-Count': value['crime_count'],
'Crime-Rate': value['crime_rate'],
'Area-Of-Responsibility': value['is_aor'],
}
}
return context
And ListApiView:
class APILocationList(generics.ListAPIView):
serializer_class = APILocationListSerializer
def get_queryset(self):
q=Blotter.objects.values('location__location_name').annotate(
address=F('location__location_name'),
latitude=F('location__loc_lat'),
longitude=F('location__loc_long'),
population=F('location__pop'),
crime_count=Count('complaints', filter=Q(complaints__is_active=True) and Q(complaints__isnull=False)),
crime_rate=(Cast(F('crime_count'), FloatField())/Cast(F('population'), FloatField()))*100000,
is_aor=F('location__is_AOR')
)
q1 = q.filter(location__is_AOR=True).order_by('address')
query_search = self.request.GET.get("q")
if query_search:
q1 = q.filter(Q(location__is_AOR=True) and Q(location__location_name__icontains=query_search)).order_by('address')
return q1
I'm new to django and DRF. I want to achieve a result like this in my API Not Achieved
but this is the result that i've achieved so far Achieved
As you can see in the picture, I want to count the crime trend (highest count of a crime and the crime itself) in every location.
My questions are:
Is this even achievable/possible to get these results using just one query?
If yes, how?
If no, is there any other way to achieve these kind of results?
Thank you in advance!

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