please help with the form is first loaded in the form fields display data from a database.
models:
class Status(models.Model):
status = models.CharField(max_length=40, blank=False, )
#classmethod
def get_status_list(self):
status_list = list()
status_list.append(('', 'no selected'))
for values_ins in Status.objects.all().values_list('id', 'status'):
status_list.append(values_ins)
return status_list
class UserProfile(User):
name1 = models.CharField('Имя', max_length=30, blank=True, null=True, )
name2 = models.CharField('Отчество', max_length=30, blank=True, null=True, )
status = models.ForeignKey(Status, verbose_name='Статус', blank=True, null=True, )
forms:
class PersonalDataForm(forms.ModelForm):
status = forms.ChoiceField(widget=forms.Select, choices=Status.get_status_list(),label='Статус',required=False, )
class Meta:
model = UserProfile
fields = ('name1', 'name2', )
views:
#login_required
def personal_data_page(request):
entry_user_profile = UserProfile.objects.get(user_ptr_id=request.user.id)
form = PersonalDataForm(instance=entry_user_profile)
if request.method == 'POST':
form = PersonalDataForm(request.POST, instance=entry_user_profile)
if form.is_valid():
form.save()
entry_user_profile.save()
return HttpResponseRedirect('/userprofile/personal_data_page_changed/')
t = loader.get_template('personal_data_page.html')
c = RequestContext(request, {'form': form,})
return HttpResponse(t.render(c))
template:
{{ form.name1 }}
{{ form.name2 }}
{{ form.status }}
the problem is that the form is first loaded the user can see the data from the database in the fields: "name1", "name2". but does not see the data from the database in the "status" (it shows a point "no selected", but must show the item corresponding to the value in the table UserProfile.status_id)
I need to when you first load the form in the "status" indicated a certain value. please help
You are using a model form but then you have override the status field in your form so you need to set the initial value manually by overriding the __init__ method (one way of doing it, it can be done in other ways also):
class PersonalDataForm(forms.ModelForm):
status = forms.ChoiceField(
widget=forms.Select,
choices=Status.get_status_list(),
label='Статус',
required=False
)
def __init__(self, *args, **kwargs):
super(PersonalDataForm, self).__init__(*args, **kwargs)
self.fields["status"].initial = self.instance.status.id # this line sets the value
class Meta:
model = UserProfile
fields = ('name1', 'name2', )
Following are some improvements for your other pieces of code.
Simplified get_status_list method:
#classmethod
def get_status_list(self):
status_list = Status.objects.all().values_list('id', 'status')
status_list.insert(0, ('', 'no selected'))
return status_list
You don't need to have entry_user_profile.save() after form.save(). The form save method will return the updated the profile instance by default. So following two lines:
form.save()
entry_user_profile.save()
Simplified as:
entry_user_profile = form.save()
Related
Hello so I've a form and I'm trying to make it so that when that form is validated. But before it is saved. It will create a new instance of a EC_Node and save the command given in the Command_Form not only to the Command_Node but to the EC_Nodes. Which should have a manytoone relationship with the Command_Nodes and which should record all commands send to a command_node. But this will only work if when entering a command for the Command_Node I also capture that in a EC_Node. Which I don't know how to do exactly although I'm some ideas.
So any advice would be greatly appreciated. Relevant Code follows.
Relevant views.py
def update(request, host_id):
host_id = Command_Node.objects.get(pk=host_id)
form = Command_Form(request.POST or None, instance=host_id)
if form.is_valid():
# Original suggestion was command_form = Command_Form.objects.first()
command_form = form['host_id']
command_form.EC_Node_set.all() # <- not sure with all _ and Maj here
form.save()
return redirect('home')
return render (request, 'update.html', {'host_id':host_id,'form':form})
forms.py
class Command_Form(ModelForm):
class Meta:
model = Command_Node
fields = ('host_id','current_commands')
host_id = forms.ModelChoiceField(
required=True,
queryset=Beacon.objects.all(),
widget=forms.SelectMultiple(
attrs={
'class': 'form-control'
},
)
)
current_comamnds = forms.ChoiceField(
required=True,
choices=CHOICES
)
def save(self, **kwargs):
EC_Node.objects.create(
command=self.cleaned_data["current_commands"],
Command_node=self.instance
)
return super().save(**kwargs)
models.py
class Command_Node(models.Model):
host_id = models.ForeignKey(Beacon, on_delete=models.CASCADE)
current_commands = models.CharField(choices=CHOICES, max_length=50, null=True)
def __str__(self):
return str(self.host_id)
class EC_Node(models.Model):
Command_node = models.ForeignKey(Command_Node, on_delete=models.DO_NOTHING)
command = models.CharField(choices=CHOICES, max_length=50, null=True)
def __str__(self):
return str(self.Command_node)
When I try to update things, via the update-view the present error I'm getting is:
'BoundField' object has no attribute 'EC_Node_set'
Thus my question on here. Thanks.
Forms validated data are accessible in the Form.cleaned_data attribute. See the documentation.
So you need to access your user data using this dictionary:
def update(request, host_id):
host_id = Command_Node.objects.get(pk=host_id)
form = Command_Form(request.POST or None, instance=host_id)
if form.is_valid():
# Original suggestion was command_form = Command_Form.objects.first()
command_form = form.cleaned_data['host_id']
I need to update the model according to the marked checkboxes in the django shape
How can I get only some of the table fields in a query
the "checked" line should be updated through the queryset
models.py
class moIn(models.Model):
date = models.DateTimeField(auto_now_add=True, verbose_name='')
dateUpdate = models.DateTimeField(auto_now=True)
ts = models.IntegerField(verbose_name='')
pl = models.IntegerField(verbose_name='')
rem = models.IntegerField(verbose_name='')
comment = models.TextField(max_length=200, verbose_name='', blank=True)
staffer = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name='')
checked = models.BooleanField(verbose_name='', default=False)
checkedUser = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name='', blank=True, null=True, related_name='checkedUser')
by clicking this checkbox, you will need to receive database records
forms.py
class checkForm(ModelForm):
checked = fields.BooleanField(required=False)
class Meta:
model = moIn
fields = {"id", "checked"}
views.py
def dashboard(request):
if request.user.groups.filter(name='DashBoardAccess').exists():
form = checkForm
f = tableDashFilter(request.GET, queryset=moIn.objects.all())
if request.method == 'POST':
form = checkForm(request.POST)
if form.is_valid():
tt = form.save(commit=False)
data = form.cleaned_data
field = data['checked']=True
f.qs.filter(checked=field).update(checked=True, checkedUser=request.user)
return HttpResponse('ok')
else:
context = {
'filter': f,
'form': form
}
return render(request, 'dashboard/index.html', context)
else:
raise Http404()
in a line in bold, you need to get only those lines in which the checkbox is marked
f.qs.filter(checked=field).update(checked=True, checkedUser=request.user)
You can get all the fields using ".values ()" for the queryset, and to use it with foreignKey, you need to explicitly specify the model fields:
f = tableDashFilter(request.GET, queryset=moIn.objects.values('id','date','ts','pl','rem','comment','checked','staffer__username','checkedUser__username'))
"Value" from the input, it is also going to be obtained through:
Since there can be several values (marked checkboxes), there will be a ".getlist"
checkID = request.POST.getlist('checked')
querySet filter:
f.qs.filter(id__in=checkID).update(checked=True, checkedUser=request.user)
in the html template through the loop, iterate over and insert into the input value of the model id
So I'm using the Django Form Wizard to split a simplified PostForm. In one of the steps, visitors can upload different images related to the Post.
Within the done method for the SessionWizardView, I'm saving the instance first and then check for the images within the formset.
However I get the following error message;
save() prohibited to prevent data loss due to unsaved related object
I tried setting the related Post id for the formset but I'm missing something here, formsets are still something I can't really follow.. Any help is appreciated!
models.py
class Post(models.Model)
title = models.CharField(max_length=200)
description = models.TextField(max_length=1000)
def __str__(self):
return self.title
class Image(models.Model):
post = models.ForeignKey('Post', on_delete=models.SET_NULL, null=True)
file = models.ImageField(upload_to='images/', null=True, blank=True)
alt = models.CharField(max_length=200, blank=True)
views.py
FORMS = [
('title', PostCreateForm),
('image', ImageFormset)
]
TEMPLATES = {
'title': 'post_form_title.html',
'image': 'post_form_image.html'
}
class PostWizardView(SessionWizardView):
form_list = FORMS
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'temp/'))
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
def done(self, form_list, form_dict, **kwargs):
instance = Post()
for form in form_list:
instance = construct_instance(form, instance)
instance.save()
post_id = instance.pk
if 'image' in form_dict:
formset = form_dict['image']
if formset.is_valid():
formset.save(commit=False)
for form in formset:
form.post = post_id
formset.save()
forms.py
class PostCreateForm(forms.ModelForm):
class Meta:
model = Image
fields = '__all__'
ImageFormset = inlineformset_factory(
Post,
Image,
form = PostCreateForm,
min_num=1,
can_delete=True
)
You should save the individual forms as you loop through them:
if formset.is_valid():
for form in formset:
if form.is_valid():
f = form.save(commit=False)
f.post = post_id
f.save()
I am using a model form, and the field is a foreign key, to another the model, the foreign key model contains a choice field(status) which i want filter based on user group,such that if a user belongs to a group, for example if the user in a group DEVELOPER, the status choices available will be 'Weekly Task' and 'Daily Task'
models.py
class ScrumyGoals(models.Model):
user_name=models.ForeignKey('ScrumyUser', on_delete= models.CASCADE, null= True)
status_id = models.ForeignKey('GoalStatus', on_delete=models.CASCADE,null=True)
goal_type = models.CharField(choices=GOAL_TYPE, max_length=64, default='DT')
def __str__(self):
return '{},{}'.format(self.user_name,self.status_id)
class GoalStatus(models.Model):
GOALS_TYPE= (('DT','Daily Task'),
('WT','Weekly Task'),
('V','Verified'),
('D','Done'),
)
title = models.CharField(max_length=254, null=True)
task_id=models.IntegerField(default=1,null=False)
description =models.CharField(max_length=254)
verified_by=models.ForeignKey('ScrumyUser', on_delete= models.CASCADE, null=True)
status=models.CharField(choices=GOALS_TYPE, max_length=2, default='DT')
forms.py
class ChangeTaskForm(forms.ModelForm):
class Meta:
model = ScrumyGoals
fields = ['status_id']
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ChangeTaskForm, self).__init__(*args, **kwargs)
if user.groups.filter(name ='DEVELOPER').exists():
self.fields['status'].choices = (('WT','Weekly Task'), ('DT','Daily Task'),)
views.py
def changetask(request):
if request.method == 'POST':
form = ChangeTaskForm(request.POST, user=request.user)
if form.is_valid():
return HttpResponseRedirect('/index/')
else:
form = ChangeTaskForm(user=request.user)
return render(request, 'oderascrumy/changetask.html', {'form': form})
The form only currently shows the status_id , it doesn't show the choices (ie "status")
so in essence what i want is this if the logged in user is in group say "DEVELOPER", The user can only change the goal (ie "status_id") choice (ie "status") from weekly task to daily task and the form is saved
Does it work if you remove the if from forms.py, i.e. are you positive the Group with name 'DEVELOPER' exists, and that the user you're testing with is actually in that group?
An alternative might be to always include status in fields, then just conditionally show that field in the template with if user.groups in ['DEVELOPER'].
In my code CreateNoticeForm is working fine and all data gets saved perfectly except
many to many field which is tags in my notice model.Although it is working on admin site and gets saved.
here is my code
models.py
from django.db import models
from django.contrib.auth.models import User
from wysihtml5.fields import Wysihtml5TextField
# Create your models here.
class Tag(models.Model):
# For notice tags
name = models.CharField(max_length=70, unique=True)
def __str__(self):
return self.name
class Notice(models.Model):
# Notice Store
headline = models.CharField(max_length=140)
description = Wysihtml5TextField()
file_name = models.FileField(upload_to='static/noticefiles/', blank=True)
created_by = models.ForeignKey(User)
fors = models.CharField(max_length=1, choices=(('F','Faculty'),('S','Student'),) )
last_date = models.DateField()
tags = models.ManyToManyField(Tag, blank=True)
post_time = models.DateTimeField(auto_now_add=True)
update_time = models.DateTimeField(auto_now=True)
def __str__(self):
return self.headline
forms,py
FORS_CHOICES = (('F','Faculty'),('S','Student'))
class CreateNoticeForm(ModelForm):
fors = forms.ChoiceField(label="Related To",
choices=FORS_CHOICES,
)
class Meta:
model = Notice
fields = ('headline', 'description',
'fors', 'last_date', 'tags','file_name')
widgets = {
'description': Wysihtml5BootstrapWidget(),
'last_date': SelectDateWidget()
}
def __init__(self, *args, **kwargs):
super(CreateNoticeForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_id = 'create_notice_form_id'
self.helper.form_class = 'form-horizontal'
self.helper.form_method = 'post'
self.helper.label_class = 'col-lg-2'
self.helper.field_class = 'col-lg-8'
self.helper.layout = Layout(
Fieldset('Create Notice',
'headline',
'description',
Field('fors', label='Audience'),
MultiWidgetField('last_date',
attrs=(
{'style': 'width: 33.33%; display: inline-block;'}
)
),
'tags',
'file_name',
FormActions(
Submit('save', 'Create Notice',
css_class='btn-warning col-lg-offset-2'),
),
),
views.py
def create_notice(request):
context = RequestContext(request)
posted = False
if request.method=='POST':
create_notice_form = CreateNoticeForm(data=request.POST, files=request.FILES)
if create_notice_form.is_valid():
cnf = create_notice_form.save(commit=False)
cnf.created_by = request.user
cnf.save()
posted = True
else:
print(create_notice_form.errors)
else:
create_notice_form = CreateNoticeForm()
return render_to_response('notices/createnotice1.html',
{'create_notice_form': create_notice_form,
'posted': posted,},
context)
You have to call save_m2m():
cnf = create_notice_form.save(commit=False)
cnf.created_by = request.user
cnf.save()
create_notice_form.save_m2m()
Excerpt from the documentation:
If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn’t possible to save many-to-many data for an instance until the instance exists in the database.
To work around this problem, every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you’ve manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data.
You have to Call the following after validating the form:-
if create_notice_form.is_valid():
parent = create_notice_form.save(commit=False)
parent.save()
create_notice_form.save_m2m()
I hope this will help you