Updating database on Django - django

Good day SO.
I want to ask something basic. I tried on my end to update my data from html to save to database but to no avail. My Model structure is Account extends to AbstractBaseUser, BaseUserManager and CompanyAccount links to Account by OneToOneField. I can say that my Model should have no problem since I can Register Account and Company Account without any problems.
EDIT
Now I can save my CompanyAccount but the link to Account was removed.
Still trying to check which is the problem
views.py
#login_required(login_url='/login/')
def user_my_page(request, *args, **kwargs):
context = {}
context['form_type'] = 'update'
context['account_type'] = request.user.account_type
if request.POST:
if request.user.account_type == 1:
company = CompanyAccount.objects.get(account=request.user)
account_form = CompanyAccountForm(request.POST, instance=company)
if account_form.is_valid():
account_form.save()
print(request.POST)
print('SAVE')
else:
print('ERROR')
forms.py
class AccountCreationForm(UserCreationForm):
accuser_id = forms.CharField(max_length=10, help_text="Required")
class Meta:
model = Account
fields = ("accuser_id", "password1", "password2")
class CompanyAccountForm(forms.ModelForm):
class Meta:
model = CompanyAccount
fields = "__all__"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['company_name'].widget.attrs.update({'class': 'content-input'})
self.fields['company_name_kana'].widget.attrs.update({'class': 'content-input'})
print(request.POST)
<QueryDict: {'csrfmiddlewaretoken': ['6zrwt68PNiJKrgZcKanDcVJkqAtogbQbNk2wHwjOzg7ybfq3Lyei9ZqdbmAJcYrV'], 'company_name': ['TESTING'], ....etc
This part here, it does print SAVE on my terminal but it does not save to the database.

I got it. Created a new Form for update then excluded the Account.
class CompanyAccountUpdateForm(forms.ModelForm):
class Meta:
model = CompanyAccount
fields = "__all__"
exclude = ('account',)
Then used the new Form to my update view

Related

Django - how to make tags on a per user basis

on a Django project that uses django-taggit (https://pypi.org/project/django-taggit/)
I would like to make tags on a per user basis, this way each user can define its own set of tags.
I'm settings up the following model:
# models.py
from django.db import models
from taggit.models import Tag
from django.contrib.auth.models import User
# Create your models here.
class MyTag(Tag):
""" You must make taggit.models.Tag an abstract model"""
user = models.ForeignKey(User, related_name="to_tags", on_delete=models.SET_NULL)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def save(self, args, kwargs):
user = kwargs.pop('user')
self.user = user
super(MyTag, self).save(*args, **kwargs)
then to manage I'd use a normal form ( in this case the tags are for a Photo model)
# forms.py
class PhotoForm(forms.ModelForm):
class Meta:
model = Photo
fields = ('name', 'artistic_name', 'description', 'tags', 'is_top', 'note')
widgets = {
'description': forms.Textarea(attrs={'rows': 2}),
'note': forms.Textarea(attrs={'rows': 2})
}
now the Question...how to I save the user in the MyTag model?
I have to pass it to the form instance in the view doing something like:
def photo_detail(request, photo_id):
...
form = PhotoForm(request.POST or None, user=request.user)
...
if request.method == 'POST':
if form.is_valid():
form.save()
...
first question...should I pass the user when I make the form instance, or when I call the save method...?
Then I would have to intercept the Tag.save()...but here I'm lost.
Any help is appreciated.
Thank you very much!
Carlo

django fill form field automatically from context data

I have a form attached to a DetailedView and its working fine when saved. I would like the form field(position) to be prepopulated with the value coming from the slug of the detailed view(e.g jobs/human-resource-manager). The Model of the form field has a Foreignkey to the JobPost model. Need help. Part of my view looks like this
class JobsDetailView(DetailView):
model = JobPost
template_name = 'job_post-detail.html'
def get_context_data(self, **kwargs):
context = super(JobsDetailView, self).get_context_data(**kwargs)
context['position'] = JobPost.objects.order_by('position')
context['job_app_form'] = JobsForm()
return context
foms.py
from django import forms
from job_post.models import JobsApplied
class JobsForm(forms.ModelForm):
class Meta:
model = JobsApplied
fields = '__all__'
def form_valid(self, form):
form.instance.customuser = self.request.user
return super().form_valid(form)
I'm assuming you do not want your users to be able to interact with or change these prefilled values.
I'm making a comments/review model and I want it to automatically link reviews to the people they are about
models.py
class Review(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
...
I hide the person field in the ReviewsForm to prevent user input by either omitting it from the 'fields' or adding it to an 'exclude'.
forms.py
class ReviewsForm(forms.ModelForm):
class Meta:
model = Review
fields = ('rating', 'summary', 'review_text')
Then, when processing the form in the view, I use commit=False so I can manipulate field values before saving to the database.
Include prefilled values, save and then redirect the user wherever is ideal
views.py
def person(request, area_slug, category_slug, person_id):
...
if form.is_valid():
pending_review = form.save(commit=False)
pending_review.person = Person.objects.get(pk = person_id)
pending_review.save()
return HttpResponseRedirect(...)
django fill form field automatically from context data for django form and django formsets
For formsets in forms.py
StoreRequestAccessoryUpdateFormSet = forms.modelformset_factory(StoreRequestAccessory, form=StoreRequestAccessoryUpdateForm, exclude=["storeRequestId"], can_delete=True)
In get_context_data you can add it as you like for django
class StoreRequestUpdateView(LoginRequiredMixin, UpdateView):
template_name = "Inventory/Stock/StoreRequest/StoreRequestUpdateView.html"
model = StoreRequest
fields = ["fromStoreId", "toStoreId", "reference", "status", "remark"]
def get_context_data(self, **kwargs):
context = super(StoreRequestUpdateView, self).get_context_data(**kwargs)
print(self.object.pk)
context.update({
# "StoreRequestForm": context.get("form"),
"StoreRequestForm": StoreRequestUpdateForm(instance=StoreRequest.objects.get(id=self.object.pk)),
"StoreRequestAccessoryForm": StoreRequestAccessoryUpdateFormSet(
queryset=StoreRequestAccessory.objects.filter(storeRequestId=self.object.pk),
prefix="storereq_accessory_form"),
})
return context

Manually filling disabled fields of Django ModelForm

I am facing the following scenario: I have a Django model class called Contact, which looks something like:
class Contact(models.Model):
first_name = models.CharField(max_length=70)
last_name = models.CharField(max_length=70)
company = models.ForeignKey(Company) // should be disabled in user-facing forms
organizations = models.ManyToManyField(Organization) // should be disabled and hidden in user-facing forms
// some other fields not relevant to this question
Both users of the app and administrators should be able to create objects of type Contact and store it in the database. However, for a user this should be restricted in the way that he cannot freely chose the company field of a Contact object. For this, I have created a base ModelForm called ContactForm, intended to be used by administrators, and a restricted user-facing child class called RestrictedContactForm. The code looks as follows:
class ContactForm(forms.modelForm):
class Meta:
model = Contact
fields = ['first_name', 'last_name', 'company', 'organizations']
class RestrictedContactForm(ContactForm):
class Meta(ContactForm.Meta):
widgets = {'organizations': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
super(RestrictedContactForm, self).__init__(*args, **kwargs)
// Maybe populate company and organization here somehow?
self.fields['company'].disabled = True
self.fields['organization'].disabled = True
The RestrictedContactForm is rendered to the user once he decides to create a new contact. Clearly, as both the company and organization fields are mandatory, they need to be manually injected somehow. It is exactly here where my problem lies: I haven't managed to populate these fields by hand.
Below you can find an outline of the view function implementing the logic of a user initiated creation.
def create_contact(request, company_pk):
company = Company.objects.get(pk=company_pk)
organization = Organization.objects.get(...)
if request.method == 'POST':
// Add company.pk and organization.pk to POST here?
// Pass data dictionary manually populated from POST and
// with company.pl and organization.pk to constructor?
contact_form = RestrictedContactForm(request.POST, request.FILES)
// Add company.pk and organization.pk to contact_form.data
// here (after making it mutable)?
if contact_form.is_valid():
contact_form.save()
return redirect(...)
return render(...)
contact_form = ContactForm(initial={'company': company, 'organizations': organization})
I have already tried every suggestion appearing in the comments above. The form simply never validates. My question hence is, what would be the correct way of doing this? Moreover, is the approach outlined at least conceptually right?
The project uses Django 1.9.
If the company and organization fields are not changeable by the user, then they should not be included in the fields list at all in RestrictedContactForm.
What you can do instead is pass the known values for organization and company into the constructor of the form, and then assign them to the object before you actually create it in the database.
class RestrictedContactForm(ContactForm):
class Meta(ContactForm.Meta):
fields = ['first_name', 'last_name', ]
def __init__(self, company, organization, *args, **kwargs):
super(RestrictedContactForm, self).__init__(*args, **kwargs)
self.company = company
self.organization = organization
def save(self, commit=True):
instance = super(RestrictedContactForm, self).save(commit=False)
if not instance.pk:
instance.company = self.company
instance.organization = self.organization
if commit:
instance.save()
return instance
def create_contact(request, company_pk):
# ...
if request.method == 'POST':
company = Company.objects.get(pk=company_pk)
organization = company.organization
contact_form = RestrictedContactForm(company, organization, request.POST, request.FILES)
# ...
# ...
I've always done this using the form_valid method. In this case, in the form_valid method of the child form:
def form_valid(self, form):
form.instance.company = foo
form.instance.organisation = bar
return super().form_valid(form)
This populates the missing field, and then saves the form.

what does the autocomplete-light return?

I have recently installed autocomplete-light in my app.
Autocomplete filters through the field called 'name' in a table called institution. However, what is post through the view is the 'id' of the same object, not the name.
Does anyone know why that is?
My view is:
class UserAccountsUpdate(UpdateView):
context_object_name = 'variable_used_in `add_user_accounts.html`'
form_class = AddUserAccountsForm
template_name = 'add_user_accounts.html'
success_url = 'add_user_accounts.html'
def add_user_institution_details(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = AddUserAccountsForm(request.POST)
# check whether it's valid:
if form.is_valid():
institution_selected = Institution.objects.get(id=name)
form.save()
return render(request)
#get object
def get_object(self, queryset=None):
return self.request.user
The form is:
class AddUserAccountsForm(forms.ModelForm):
name = forms.ModelChoiceField(required=True, queryset=Institution.objects.all(), widget=autocomplete_light.ChoiceWidget('InstitutionAutocomplete'), label="")
class Meta:
model = Institution
fields = ('name',)
autocomplete-light's ChoiceWidget uses the Model's PrimaryKey for post requests by default, which in your case is id.
Since you did not post your models.py I can only assume that name is a CharField in the Institution model and you are just using autocomplete here to simplify the adding of a name.
To realize this use TextWidget and forms.CharField:
class AddUserAccountsForm(forms.ModelForm):
name = forms.CharField(
required=True,
widget=autocomplete_light.TextWidget('InstitutionAutocomplete'),
label="",
)
class Meta:
model = Institution
fields = ('name',)

custom form author - auto save author to DB

I have a custom form... I'd like to auto save the author (authenticated user) for the form data. I'm using ModelForm for creating the form.
models.py
class Tracker(models.Model):
client = models.ForeignKey(Clients)
user = models.ForeignKey(User)
description = models.TextField()
...
I have also linked the custom profile to the django users table... also the auth works fine... I can read the user and id...
forms.py
class TrackerForm(ModelForm):
def __init__(self, *args, **kwargs):
super(TrackerForm, self).__init__(*args, **kwargs)
self.fields.keyOrder = ['date_job_start','date_job_end','description','onsite','billable','client']
class Meta:
model = Tracker
widgets = {
'client': HiddenInput(),
}
When the form is created from the upper class and I try to save it... it wants the user data (missing warning). How can I change it so that it would automatically save the authenticated user instead of asking for it?? I know that I dont' have the user field defined here... that's because I don't want a dropdown for it... I want the user to be saved from the auth...without any selection or display...
P.S.: I know about the initial option... there must be a better way?
Thanks!
BR
class TrackerForm(ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(TrackerForm, self).__init__(*args, **kwargs)
self.fields.keyOrder = ['date_job_start','date_job_end','description','onsite','billable','client']
class Meta:
model = Tracker
widgets = {
' client': HiddenInput(),
}
exclude = ('user',)
def save(self):
obj = super(TrackerForm, self).save(commit=False)
obj.user = self.user
obj.save()
return obj
And in view:
form = TrackerForm(user=request.user) #and other parameters