Update a particular field in django forms and not be able to edit the others - django-models

I am trying to create a expense claim app, i have created a form where a user can claim a expense ,when the admin Logs in the following webpage in the picture appears and the webpages iterates all the claims that have claim_status == Null, i want the admin to be able to accept or reject the claim from the dropdown and it to update the value for that object in the database and webpage to refresh and that claim showing no more
I have given a initial value of Null for the ExpenseClaim model and when user fills the expense claim form he cannot see the claim_status field
please see my models
class ExpenseClaim(models.Model):
reference_number = models.AutoField(primary_key=True)
employee_name = models.CharField(max_length=150)
employee_ID = models.CharField(max_length=150)
claim_initiating_date = models.DateTimeField(auto_now=True)
invoice_date = models.DateField()
invoice_location = models.CharField(max_length=150)
biller_name = models.CharField(max_length=150)
invoice_category = models.CharField(max_length=150)
price = models.DecimalField(decimal_places=2, max_digits=10, null=False , default=0.00)
GST = models.DecimalField(decimal_places=2 ,max_digits=10, null=False , default=0.00)
CGST = models.DecimalField(decimal_places=2 ,max_digits=10, null=False , default=0.00)
IGST = models.DecimalField(decimal_places=2, max_digits=10, null=False , default=0.00)
Total_amount = models.DecimalField(decimal_places=2 ,max_digits=10, null=False , default=0.00)
mode_of_payement = models.CharField(max_length=20)
Payment_reference = models.BooleanField()
invoice = models.FileField()
claim_status = models.CharField(default=None , max_length=10)
payment_status = models.CharField(default= None , max_length=10)
Following is my models field i tried to create a new form but that just creates a new object in the database i want to update the existing one
invoice_category_choices =[
('food',"food"),
('travel',"travel"),
('accodmodation',"accomodation"),
('fuel',"fuel"),
# ('others',"others"),
]
claim_status_choices = [
('accepted' , 'accepted'),
('rejected' , 'rejected')
]
payment_status_choices =[
('paid' , 'paid'),
('notpaid' , 'notpaid')
]
class ExpenseClaimForm(forms.ModelForm):
class Meta:
model = ExpenseClaim
exclude = [
"employee_name",
"employee_ID",
"claim_status",
"payment_status"
]
widgets = {
'invoice_date': forms.DateInput(format=('%m/%d/%Y'), attrs={'class':'form-control', 'placeholder':'Select a date', 'type':'date'}),
'invoice_category':forms.Select(choices= invoice_category_choices),
'claim_status':forms.Select(choices= claim_status_choices)
}
class ClaimStatusForm(forms.ModelForm):
class Meta:
model = ExpenseClaim
fields = [
"claim_status",
]
widgets = {
'claim_status':forms.Select(choices= claim_status_choices)
}

forms.py
class ClaimStatusForm(forms.ModelForm):
class Meta:
model = ExpenseClaim
fields = [
"claim_status",
]
widgets = {
'claim_status':forms.Select(choices= claim_status_choices)
}
views .py
def admin_update_view(request , reference_number):
post = get_object_or_404(ExpenseClaim , reference_number=reference_number)
form = ClaimStatusForm(instance=post)
if request.method == 'POST':
post = get_object_or_404(ExpenseClaim , reference_number=reference_number)
form = ClaimStatusForm(request.POST)
if form.is_valid():
claim_status = form.cleaned_data.get('claim_status')
post.claim_status = claim_status
post.save()
return redirect('/admin/')
context = { "form":form , "initialize_context" : initialize_context(request)}
return render(request , 'graphauth/adminupdate.html' , context)
urls.py
path('adminupdate/<int:reference_number>', views.admin_update_view , name='adminupdate'),
admin.html
update

Related

How can I create multiple related objects inside a view with cleaned data from two Django forms on the same page

I have 4 related Django Models ModifiedUser and Profile defined as follows . I am trying to create the person responsible for the activity,through a person model form. Through a person profile model form I am trying to add their profile details which includes the related person,country etc. Using these details I want to create a second person, called related user. Then I want to assign the two people to the activities via their Roles.
Models
'''
Class ModifiedUser:
email = models.EmailField(
max_length=255,blank=True,null=True,unique=True)
...
Class Profile:
modified_user = models.ForeignKey(ModifiedUser)
related_user = models.EmailField(
max_length=255,blank=True,null=True)
...
class Activity:
person = models.ManyToManyField(Profile,related_query_name='actor',related_name=' person', through='RoleAssignment')
class RoleAssignment:
person = models.ForeignKey(Profiles,on_delete=CASCADE,related_name="role")
feedback = models.ForeignKey(Activity,on_delete=CASCADE)
...
'''
Forms:
'''
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = '__all__'
class ModifiedUserForm(forms.ModelForm):
class Meta:
model = ModifiedUser
fields = '__all__'
'''
View
'''
from profiles.models import Profile, ModifiedUser,Activity
from .forms import ResponsibleForm, ModifiedUser
def add_activity_owner(request):
activity = Activity.objects.create(initiatedby=currentuser,updatedby=currentuser)
if request.method == 'POST':
responsibleform = ResponsibleForm(request.POST, request.FILES)
profileform = ProfileForm(request.POST, request.FILES)
if all([receiverform.is_valid(), detailform.is_valid()]):
owner_firstname =responsibleform .cleaned_data['Phone']
owner_lastname = responsibleform .cleaned_data['Address']
owner_email = responsibleform .cleaned_data['email']
relatedperson_email= profileform.cleaned_data['related_user'],
country = profileform.cleaned_data['country'],
gender = profileform.cleaned_data['gender'],
relatedperson,person_created = ModifiedUser.objects.get_or_create(email=relatedperson_email,FirstName=NULL,LastName=NULL)
owner,owner_created=Profiles.objects.get_or_create(email=owner_email,FirstName=owner_firstname,Lastame=owner_lastname)
owner_profile ,owner_created= Profiles.objects.get_or_create(user=owner,
related_user= relatedperson_email,
country = country,
gender = gender,
owner_role = RoleAssignment.objects.create(activity=activity,person=owner,role=role['owner'])
related_person_role = RoleAssignment.objects.create(activity=activity,person=relatedperson,role=role['actor'])
context['relateduser']=relateduser
context['owner']=owner
context['owner_role']=owner_role
return redirect(selectroles,activity)
else:
responsibleform = GiverForm()
profileform = UserProfileUpdateForm()
profileform':profileform})
return render(request,'addowner.html',context)
'''

Django Post request for many to many field ValueError

I am working on a post request in which the user chooses from a list of tags and makes combinations of tags. The combination of tags should then be posted. Nothing should get changed in the Tag table.
These are the models:
models.py
class Tag(models.Model):
name = models.CharField(max_length=256)
language = models.CharField(max_length=256)
objects = models.Manager()
def __str__(self):
"""Return a human readable representation of the model instance."""
return self.name or ''
#property
def tags(self):
tags = self.tagging.values('tag')
return tags.values('tag_id', 'tag__name', 'tag__language')
class Combination(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
gameround = models.ForeignKey(Gameround, on_delete=models.CASCADE, null=True)
resource = models.ForeignKey(Resource, on_delete=models.CASCADE, null=True)
tag_id = models.ManyToManyField(Tag, null=True)
created = models.DateTimeField(editable=False)
score = models.PositiveIntegerField(default=0)
objects = models.Manager()
def __str__(self):
return str(self.tag_id) or ''
This is the serializer for Combination.
serializers.py
class CombinationSerializer(serializers.ModelSerializer):
tag_id = TagWithIdSerializer(many=True, required=False, write_only=False)
resource_id = serializers.PrimaryKeyRelatedField(queryset=Resource.objects.all(),
required=True,
source='resource',
write_only=False)
gameround_id = serializers.PrimaryKeyRelatedField(queryset=Gameround.objects.all(),
required=False,
source='gameround',
write_only=False)
user_id = serializers.PrimaryKeyRelatedField(queryset=CustomUser.objects.all(),
required=False,
source='user',
write_only=False)
class Meta:
model = Combination
depth = 1
fields = ('id', 'user_id', 'gameround_id', 'resource_id', 'tag_id', 'created', 'score')
def create(self, validated_data):
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
score = 0
tag_data = validated_data.pop('tag_id', None)
combination = Combination(
user=user,
gameround=validated_data.get("gameround"),
resource=validated_data.get("resource"),
created=datetime.now(),
score=score
)
combination.save()
for tag_object in tag_data[0]:
combination.tag_id.add(tag_object)
return combination
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['tag_id'] = TagWithIdSerializer(instance.tag_id.all(), many=True).data
return rep
I have tried posting the following JSON object to the database:
{
"gameround_id": 2015685170,
"resource_id": 327888,
"tag_id": [{"id": 2014077506, "name": "corwn","language": "en"}]
}
I am getting a ValueError: Field 'id' expected a number but got 'name'.
How can I fix this issue?
you need to provide tag id for each tag not all tag data,
Try like this
{
"gameround_id": 2015685170,
"resource_id": 327888,
"tag_id": [2014077506,2014077507]
}

How check UniqueConstraint in Django with CreateView and custom forms if field set in view?

I do:
I define UniqueConstraint (also try with 'unique_together') in model:
class Project(models.Model):
class Meta:
constraints = [
models.UniqueConstraint(
fields=['company', 'name'], name="unique_project_name_in_company"
)
]
name = models.CharField(blank=False, max_length=256)
company = models.ForeignKey(
Company,
on_delete=models.CASCADE
)
I set company in form_valid in view (I think it's reason of my problem):
class ProjectCreateView(LoginRequiredMixin, generic.CreateView):
model = Project
form_class = ProjectForm
def form_valid(self, form):
form.instance.company = self.request.user.company
return super().form_valid(form)
I try define message for 'unique_project_name_in_company' in form:
class ProjectForm(forms.ModelForm):
model = Project
class Meta:
model = Project
fields = ['name']
error_messages = {
NON_FIELD_ERRORS: {
'unique_project_name_in_company': "Name isn't unique!",
}
}
Unexpected behavior
If I submit form with non-unique pair (inputed non-unique name) I want get my custom error_message but I get:
500 IntegrityError UNIQUE constraint failed: company_id, name

how to filter foreign key in django form without passing foreign key value?

I have created two models in my django project AddStudent and Fee Entry as shown below.
models.py
class AddStudent(models.Model):
enrollment_no = models.BigIntegerField(primary_key=True)
student_name = models.CharField(max_length=500,null=True)
gender = models.CharField(max_length=1,choices=GENDER_CHOICES)
course = models.ForeignKey(CourseMaster, on_delete=models.DO_NOTHING, null=True)
category= models.ForeignKey(CatMaster, on_delete=models.DO_NOTHING, null=True)
admission_year = models.IntegerField(('year'), choices=YEAR_CHOICES, default=datetime.datetime.now().year)
college = models.ForeignKey(CollegeMaster, on_delete=models.DO_NOTHING, null=True)
branch = models.ForeignKey(BranchMaster,on_delete=models.DO_NOTHING, null=True)
current_semester = models.IntegerField(null=True)
address = models.CharField(max_length=1000,null=True)
city = models.CharField(max_length=100,null=True)
district = models.CharField(max_length=100,null=True)
state = models.CharField(max_length=100,null=True)
student_contact = models.BigIntegerField()
parent_contact = models.BigIntegerField()
def get_absolute_url(self):
return reverse('add_student:index')
def __str__(self):
return str(self.enrollment_no) + ' - ' + self.student_name
class FeeEntry(models.Model):
student = models.ForeignKey(AddStudent,on_delete=models.DO_NOTHING)
fee_detail = models.ForeignKey(FeeMaster,on_delete=models.DO_NOTHING)
fee_sem = models.IntegerField(null=True)
payment_date = models.DateField(("Date"), default=datetime.date.today)
pay_method = models.BooleanField(choices=BOOL_CHOICES)
cheque_no = models.CharField(max_length = 100, null=True, blank=True)
bank_name = models.CharField(max_length = 200, null=True, blank=True)
def __str__(self):
return str(self.id) + ' - ' + str(self.student) + ' - ' + self.student.student_name
Now when user search particular student for example student id = 1 than student profile page will open and there is another button addfee. My problem is when user click on add fee all 500 student list is appear in dropdown list. i want to create fee for searched student only.
forms.py
from django import forms
from .models import FeeEntry, AddStudent
from bootstrap_modal_forms.mixins import PopRequestMixin, CreateUpdateAjaxMixin
class FeeForm(PopRequestMixin, CreateUpdateAjaxMixin, forms.ModelForm):
class Meta:
model = FeeEntry
fields = ['student', 'fee_detail', 'fee_sem', 'payment_date', 'pay_method','cheque_no','bank_name']
above is my forms.py file where field 'student' will generate all 500 student list. I want only selected student for example enrollment_no=1 when user is on enrollment_no 1's page.
views.py
class FeeCreateView(PassRequestMixin, SuccessMessageMixin,
generic.CreateView):
template_name = 'add_student/create_fee.html'
form_class = FeeForm
success_message = 'Success: Book was created.'
success_url = reverse_lazy('add_student:detail')
urls.py
path('create/<int:pk>', views.FeeCreateView.as_view(), name='create_fee'),
Can anyone tell me what changes are required in this code? or can you share link of similar example like this?
The FeeForm does not know which student you want to relate it with. Because of that, it is showing you a dropdown asking which student you want to assign to the FeeEntry instance.
Remove 'student' from the form and send the form to the view. when the user submits the form, use the form_valid (form.is_valid if you are using FBV) method to assign the student to the fee_entry instance.
def form_valid(self, form):
fee_entry = form.save(commit=False)
fee_entry.student = AddStudent.objects.get(id=self.kwargs['student_id'])
fee_entry.save()
Also make sure to send the student_id in the url. You can even send it as a POST parameter(check out how to retrieve parameter from a POST request) using a hidden field in the form.

Django model inserting foreign key from same model

I am building a simple comment app in Django. The app allows replies to comments and uses the same model to store comments and replies. My issues is when I try to insert a new reply, the parentpost(FK to parent comment) inserts as NULL. When I use the admin interface to insert a reply, it properly stores the parentpost ID for the parentpost I choose. So I know the issue is not within my model but within my view.
/MODEL/
class UserPost(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(max_length=50, unique=True,
help_text='Unique value for product page URL, created from name.', editable = False)
post = models.TextField()
is_active = models.BooleanField(default=True)
meta_keywords = models.CharField("Meta Keywords", max_length=255, blank = True, null = True,
help_text='Content for description meta tag')
meta_description = models.CharField(max_length = 255, blank = True, null = True,
help_text = 'Content for description meta tag')
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
parentpost = models.ForeignKey('self', blank = True, null = True)
class Meta:
#app_label = ''
db_table = 'userposts'
ordering = ['created_at']
verbose_name_plural = 'UserPosts'
def __unicode__(self):
return self.name
#models.permalink
def get_absolute_url(self):
return ('lync_posts', (), {'posts_slug': self.slug})
def save(self):
if not self.id:
d = datetime.datetime.now()
s = d.strftime('%Y-%M-%d-%H-%M-%S-%f')
slugfield = str(self.name + s)
self.slug = slugfield
super(UserPost, self).save()
/VIEW/
def reply(request, slugIn):
parentpostIn = UserPost.objects.get(slug = slugIn)
pid = parentpostIn.id
template_name = 'reply.html'
if request.method == 'POST':
form = forms.ReplyPostForm(data = request.POST)
# create a new item
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
if form.is_valid():
nameIn = form.cleaned_data['name']
postIn = form.cleaned_data['post']
newPost = UserPost(name = nameIn, post = postIn, parentpost = pid)
newPost.save()
return render_to_response(template_name, locals(), context_instance = RequestContext(request))
else:
# This the the first page load, display a blank form
form = forms.NewPostForm()
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
You are trying to set the parentpost ForeignKey by id.
You should either use:
newPost = UserPost(name = nameIn, post = postIn, parentpost = parentpostIn)
or (see Django: Set foreign key using integer?):
newPost = UserPost(name = nameIn, post = postIn)
newPost.parentpost_id = pid

Resources