I am using model form set. If i use formset_factory then its displaying the form like this which is correct but if i use modelformset_factory then its displaying all the objects from model like this . It should be. Am I missing something? thanks
form
class MyImageForm(ModelForm):
class Meta:
model = MyImage
exclude = ('test', 'user')
MyImageFormSet = modelformset_factory(MyImage, MyImageForm)
template
{% for form in formset %}
{{ form.non_field_errors }}
<tr>
<td>{{ form.image }}</td>
<td></td>
</tr>
{% endfor %}
{{ formset.management_form }}
According to the Django documentation on modelformset, you can create MyImageFormSet as you have been doing, but simply filter it afterwards (and presumably return the new modelformset).
Create the modelformset as normal:
MyImageFormSet = modelformset_factory(MyImage, MyImageForm)
But use the modelformset with an empty query, like this:
MyImageFormSet(queryset=MyImage.objects.none())
Related
Is it possible to dinamically change a variable name in template?
In the view below I am sending to the template an url parameter called sl.
is it possible to pass that sl to the {{ devize.sl{{sl}} }} so that it changes dinamicaly ?
thank you
#login_required
def slList(request,centrudecost,SL):
queryset = Deviz.objects.filter(centrudecost_id=centrudecost)
sl = SL
print(centrudecost)
return render(request, "proiecte/sl_list.html", {"queryset": queryset,"sl":sl})
{% for devize in queryset %}
<td>{{ devize.sl{{sl}} }}</td>
{% endfor %}
You can not change the template variable dynamically but there is a workaround on the query side. You can create (annotate) a field (my_field) and fill it dynamically in the query:
field = "xyz_fieldname" # in your case field = "sl" + SL
queryset = Deviz.objects.annotate(my_field=F(field)).values('my_field',...).filter(centrudecost_id=centrudecost)
print(centrudecost)
return render(request, "proiecte/sl_list.html", {"queryset": queryset})
and in the template:
{% for devize in queryset %}
<td>{{ devize.my_field }} }}</td>
{% endfor %}
I have a problem. Consider an HTML table and it has rows and columns. I want to add a new row or column when I want it and I want it to be a record in the database. And I want to do this with django. What should I do?
I think I need to use django_table2 but I don't know how. I would be glad if you write a code sample. Thank you)
Say you have a model, you could get a list of objects like so;
def my_view(request):
context = {'object_list':MyModel.objects.all()}
return render(request, 'mypage.html', context)
Then in the template, you could do a few things to create tables:
Either, fully generate the table with Django, like so:
{% for object in object_list %}
<tr>
<td>{{object.data}}</td>
<td>{{object.data}}</td>
<td>{{object.data}}</td>
</tr>
{% endfor %}
This would create a new row for every object.
Another solution is:
{% for object in object_list %}
//Create row for every object
<tr>
{% for data in object.get_field_data %}
// Create column for every field in object
<td>{{data}}</td>
{% endfor %}
</tr>
{% endfor %}
Where get_field_data would be defined as a method on the model like so:
def get_field_data(self):
datalist = []
for field in self._meta.get_fields():
datalist.append(getattr(self, field.name))
return datalist
You could then even implement some checks on the get_field_data, for example, you could exclude fields.
def get_field_data(self):
datalist = []
for field in self._meta.get_fields():
if field.name != 'id':
datalist.append(getattr(self, field.name))
return datalist
You don't need to use any external package, you can do this easily by using the Django Template Language
Here is a code example using a ListView
# views.py
from django.views.generic import ListView
class ItemListView(ListView):
template_name = 'mytable.html'
model = MyModel
context_object_name = 'item_list'
<!-- mytable.html -->
...
<table>
<thead>
<tr>
<th>Name</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
{% for item in item_list %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.amount }}</td>
</tr>
{% endfor %}
</tbody>
</table>
...
In this way your template will have access to a list of objects called item_list which corresponds exactly to the records in the database table. You can cycle that list/queryset using a for loop that will automatically wrap that content in the html needed to make it part of the table.
I have a simple view like so:
def classticker(request):
tickermodel = Tickers.objects.all().select_related('subsector_fk')
form = TickerForm()
return render(request, 'feeds/main.html', {'v': 10, 'form': form, 'tickermodel': tickermodel})
tickermodel is successfully returning a queryset with all of the fields in the Tickers table and the Subsector table (through the subsector_fk field). This includes the fields 'ticker', 'company_name' and 'subsector' that I'm using in the template below.
When I render my template and iterate through the tickermodel queryset I cannot seem to access fields that are coming from the Subsector table. Below tic.ticker and tic.company_name are rendering as expected but tic.subsector is not. I have no idea why??
My template looks like this:
<table class="tbllist">
<tr><th>Current Tickers</th></tr>
{% for tic in tickermodel %}
<tr>
<td><input type="checkbox" name="myclass" value="{{tic.ticker}}"/></td>
<td class="selectable" data-tik="{{tic.ticker}}"><span class="uppercase">{{ tic.ticker }}</span> - {{ tic.company_name }}</td>
<td>{{ tic.subsector }}</td> <!-- <<<< this will not display >>>>> -->
</tr>
{% endfor %}
</table>
select_related doesn't somehow make the related fields available in the main model; it doesn't change the structure at all. Your related fields are still available by following the foreign key field. The thing that select_related does is to make that more efficient by doing a JOIN query so that the related objects are already populated.
You haven't shown your models so I can't tell what the actual FK field is, but you would need to do something like tic.subsector_fk.subsector.
I am using Django 1.11 for my first Django/Python project and have been stuck for a few days trying to understand Formsets in order to create a form that will allow the creation of multiple model instances through one form. Any assistance that could be provided to help me understand and pass this issue will be greatly appreciated!
The way I have been approaching it is as follows:
I have the following model:
class Task(models.Model):
client_name = models.ForeignKey(Client,null=True,blank=True,on_delete=models.DO_NOTHING)
description = models.CharField(max_length=255)
due_date = models.DateField(null=True,blank=True,default=datetime.now)
assigned = models.ForeignKey(User,on_delete=models.DO_NOTHING)
I have the following form based on the model:
class FNTaskForm(ModelForm):
class Meta:
model = Task
exclude = ()
I have created the folllowing FormSet based on the above model & form:
TaskFormSet = modelformset_factory(Task, form = FNTaskForm, exclude=(),extra=2)
In views.py I have:
class FNTaskCreate(CreateView):
model = Task
form_class = FNTaskForm
template_name = 'fntasks.html'
def get_context_data(self, **kwargs):
context = super(FNTaskCreate, self).get_context_data(**kwargs)
context['formset'] = TaskFormSet(queryset=Task.objects.none()) # providing none
return context
And finally I render it in my html template as:
<form method="post">
{% csrf_token %}
<table class="table link-formset">
{% for form in formset %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle row1 row2 %} formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
<a class="btn btn-default" href="{% url 'clients' %}">Cancel</a>
<input type="submit" value="Next" class="btn btn-primary" />
</form>
The form appears as follows on the page:
The issue I am having and that which I am gratefully seeking on help on resolving has 2 parts:
Part 1. I cannot successfully save data into the model using this form. I am not getting any errors however I believe that the form has 3 instances, not just the 2 instances displayed and it is a third (not visible instance) that is blank and hence not allowing the form to be valid. The reason I believe this is related to issue 2 (below). When I insert print my kwargs.pop variable to test it I get 3 outputs of 'None'. So I think in my ignorance and inexperience with Django I have not used the model formset factory correctly.
Part 2. I would also like to use kwargs to set the initial value of the 'Client Name' field using the kwarg 'clientlist' passed in the URL. I have used the following to confirm the kwarg but the result is (None None None):
def __init__(self, *args, **kwargs):
clientlist = kwargs.pop('clientlist', None)
super().__init__(*args, **kwargs)
print(clientlist)
The URL is as follows for passing the kwarg:
url(r'^tasks/create/(?P<clientlist>\d+)/$',views.FNTaskCreate.as_view(),name='fntask_create'),
Is anyone able to help me pass these issues to use modelformset_factory (or any other method that is better recommended) to successfuly save multiple model instances with one form with kwargs passed into the initial fields on the form? Thanking you for your time!
I have Model with 30+ fields and I want to display about 20 of them in a table. I know that there is {{ form.as_table }} but is there a comparable function for non-form models? I am currently using
{% for name, value in article.get_fields %}
<tr>
{% if value %}
<td>{{ name }} = {{ value }}</td>
{% endif %}
</tr>
{% endfor %}
-where get_fields returns all the fields of Article. This works fine. I would guess that there is a built-in django function for doing the same thing, but I can't find it in the documentation.
I agree with #kathikr, there isn't a function built in to the model class to do this for you.
One option would be to subclass Model and add a as_table() function to it that parsed available fields and used an exclude attribute where necessary.
def as_table(self):
return "".join(["<tr><td>%s</td><td>%s</td></tr>" % (field.verbose_name, field.value_to_string(self)) for field in self._meta.fields if field not in self.exclude])
hmm, this probable shouldn't be a one-liner
def as_table(self):
result = ""
for field in self._meta.fields:
if field not in self.exclude:
result += "<tr><td>%s</td><td>%s</td></tr>" %
(field.verbose_name, field.value_to_string(self))
return result