I have a app that have 2 models:
Projecto Model's
class Projeto(models.Model):
field1 = ........
field2 = ........
Aditamento Model's
class Aditamento(models.Model):
processo = models.ForeignKey(Projet, on_delete=models.CASCADE,verbose_name="Projecto",related_name='ProcessoObjects')
field1 = .....
field2 = ....
Projecto Admin
class AditamentoInline(admin.StackedInline):
form = AditamentoForm
model = Aditamento
extra = 0
max_num = 4
class ProjetoAdmin(admin.ModelAdmin):
inlines = [AditamentoInline]
I can have 1 projeto with several aditamento's ( max:4)
Right now i want to send the field's of each aditamento to a page html to print.
when i open my object project i have 4 buttons , and when i click on of them , i want to send the fields of that aditamento corresponding that object i open.
So if i click in 3-aditamento i will send the values of aditamento i create in third and so for all.
What is the best way to do this ?
Related
How can I implement followig SQL QUERY in django rest framework
`SELECT `id` , `name_hi` as hi , `name_en` as en , false as `checked` FROM `tab_name`
where checked does not exist in the database table i.e. it is not a column .
id | hi | en | checked
1 | xx | xx | 0
2 | hi2| en2| 0
3 | hi3| en3| 0
I am using Django Rest framework.
How can I rename these fields also include checked
So far I have tried in serializer
class TabSerializer(serializers.ModelSerializer):
hi = serializers.CharField(source='name_en')
en = serializers.CharField(source='name_en')
class Meta:
model = Tab
fields =('id','name_en','name_hi')
It just return id name_en and name_hi irrespective of hi ,en and checked.
You set it in serializer for column alias
For column table alias
class TabSerializer(serializers.ModelSerializer):
hi = serializers.CharField(source='name_hi')
en = serializers.CharField(source='name_en')
class Meta:
model = TabFaultOption
fields =('id','hi','en')
Now for column which does not exist in the database you need to change in the related model
model.py
class Tab(models.Model):
id = models.IntegerField()
name_hi = models.CharField(max_length=1000)
name_en = models.CharField(max_length=1000)
checked=False
class Meta:
managed = False
db_table = 'tab'
Now in serializer include the checked column
class TabSerializer(serializers.ModelSerializer):
hi = serializers.CharField(source='name_en')
en = serializers.CharField(source='name_en')
checked= false
class Meta:
model = Tab
fields =('id','hi','en','checked')
i have user model
class User(models.Model):
first_name = models.CharField(max_length=30)
and order model
class Order(models.Model):
user = models.ForgienKey(User)
product_name = models.CharField(max_length=30)
creating 2 user
hi = User.objects.create(firs_name = 'hi')
bye = User.objects.create(firs_name = 'bye')
i created 3 orders
Order.objects.create(product_name='nokia',user=hi)
Order.objects.create(product_name='samsung',user=hi)
Order.objects.create(product_name='nokia',user=bye)
so how to count nokia has 2 users and samsung has 1 user in django using filter or aggregate or annotate? and ouput something like this(should in orderby count value)
{
"nokia":"2",
"samsung":"1"
}
Django 1.8
try this you will get your output in json format
from django.db.models import Count
Order.objects.values('product_name')
.annotate(usercount=Count('user'))
objects.create(first_name = 'hi')
hi.save()
bye = User.objects.create(first_name = 'bye')
bye.save()
Here first_name should be same as field name in models.
l=[]
for o in Order.objects.all():
l.append(str(o.product_name))
l is list which contains all products(repeated) in a list
d = {x:l.count(x) for x in l}
print d
d gives data in dictionary format, which is
{'nokia': 2, 'samsung': 1}
you can you default count function to get the count of objects with or without the filter as per your need as following.
data_dict = {}
for cat in Order.objects.all()
data_dict.update({cat.product_name : 0 })
for obj in Order.objects.all():
if obj.product_name in data_dict.keys():
data_dict[obj.product_name] += 1
printing data_dict will give you your expected output
Use following query
orders = Order.objects
.values_list('product_name')
.annotate(usercount=Count('user'))
orders = dict(orders) # This must be of your json key values.
OR
orders = dict(orders.iterlists()) # This must be of your json key values.
I'm trying to populate a django modelform with initial data provided from an external source. To achieve that I start by pull all the needed data from the external source:
url =('http://myapi.example.com')
data = urllib2.urlopen(url)
result = json.load(data)
api_data_name = result['properties']['name']
api_data_type = result['properties']['type']
Followed by populating a dict which will serve as initial data to my form:
data = {}
for field in my_model._meta.fields:
if field.name == 'name':
data[field.name] = api_data_name
form = MyEditForm(initial=data)
Then I'm passing the form to the template and the initial data is populating my text fields as expected, but now I need to be able to set a value of a select field based on a string I receive from my external source and Im not getting how can I achieve that, since doing something like:
if field.name == 'type':
data[field.name] = api_data_type
Wont do the job cause the select element has "0", "1", "2", etc as options value and not the long description i get from api_data_type variable.
How can I get the long_description from all the options <option value="1">long_description</option> of my select field in my view so i can compare each one with api_data_type?
Heres a sample of my models.py and forms.py:
#models.py
TYPE = (
('0',_(u'Type1')),
('1',_(u'Type2')),
('2',_(u'Type3')),
)
class MyModel(models.Model):
...
type=models.CharField(max_length=30,choices=TYPE,blank=True)
...
#forms.py
class MyEditForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
...
'type': Select(attrs={'class':'select-small span2'}),
...
}
Found out how to accomplish what I asked.
# For select fields
if field.name == 'classification':
for choice in field.choices:
if choice[1].lower() == api_poi_classification.lower():
data[field.name] = choice[0]
And for any of ya trying to populate many-to-many fields (as checkboxes in my case)
# Many to many fields populate
for field in hotel_poi._meta.many_to_many:
if field.name == 'views':
if u'Vista' in api_poi_review_fields:
api_vistas = api_poi_review[u'Vista']
# The api_vistas string comes from api in the format (v1; v2; v3; v4)
views = api_vistas.split(';')
choices = field.get_choices()
temp = []
for view in views:
for choice in choices:
if view.lower().strip() == choice[1].lower().strip():
temp.append(choice[0])
data[field.name]=temp
All of this could be avoided if I had direct database access... In that case i would just need to set an object instance like m = MyModel.objects.filter(id=1) and call form = MyEditForm(instance=m)
But that was not the case and that's what makes this question a bit particular.
I have two models lets say:
class superfields(Model):
fieldA = models.FloatField()
fieldB = models.FloatField()
class Meta:
abstract = True
class my_model( superfields ):
def has_history( self ):
return self.my_model_history_set.count() > 0
class my_model_history( superfields ):
reason = models.TextField()
mymodel = models.ForeignKey( my_model )
'my_model' is populated with data (under fieldA and fieldB). Whenever someone edits 'my_model's fields and saves, I don't want to save the change in this model but want to store it as a new row with all values in 'my_model_history', in addition to a 'reason' field while 'my_model' data stays the same.
What is the best way to approach this scenario in terms of custom templates, custom views, model admins etc etc. Am I doing it correctly?
To give my question above some sense, in my project, the nature of data under 'my_model' is market prices and I need to maintain a history of all the market prices ever edited with a 'reason' for the edit.
Instead of editing an existing entry, why not use that entry as initial data for a form to create a new instance? The new object gets saved, the original stays the same...
My Solution:
yes. A simple and quick solution I am following is as follows:
I create three models similar to this:
class my_super_abstract_model(Model):
#All fields I need to keep a history for:
fieldA = models.FloatField()
fieldB = models.FloatField()
class Meta:
abstract = True
class my_model( my_super_abstract_model ):
def has_history( self ):
return self.my_model_history_set.count() > 0
class my_model_history( my_super_abstract_model ):
reason = models.TextField()
history_entry_for = models.ForeignKey( my_model )
I've setup a signal:
pre_save.connect( create_history,
sender = my_model_history )
and 'create history' to be called by the pre_save() signal before saving in my_model_history:
def create_history(sender, **kwargs):
#get variables passed by the pre-save signal:
history_model = kwargs['instance']
# Get main model object
main_model = history_model.history_entry_for
# swap all common fields between history edit and main model (except id)
main_model_fields = [f.name for f in main_model._meta.fields]
history_model_fields = [f.name for f in history_model._meta.fields]
field_index = list( [f for f in history_model_fields if f in main_model_fields and f != 'id' and f != 'created_date' ] )
#loop thru to swap values:
for field_name in field_index:
temp = getattr(main_model, field_name)
setattr( main_model, field_name, getattr( history_model, field_name ) )
setattr( history_model, field_name, temp)
# After the swap, save main model object here
main_model.save()
Whenever user clicks on a my_model row for editing, I use 'my_model_history' to generate my edit form and populate it with the values from the user selected row. (Have written a view and template to do that)
So the edit form will now have:
field A -populated with values from
my_model data row
field B -populated with values from
my_model data row
Reason -empty text box
history_entry_for -hidden from view
User can now edit fieldA/fieldB. Enter a reason. Press save to trigger the signal above.
Before saving,
Signal will swap the values between
the main model(old values) and
history model(New values)
Replace and save the main model row
(with the new values).
Insert and save a new row in the
history model (with the old values)
with a reason.
Hope it helps. Let me know if there are any further questions.
I found an explanation on keeping detailed edit histories in the book 'pro Django' page 264. After a read through I'll try an implementation of what I need. Will post my approach here when I'm done
I have a couple of simple objects that have a many-to-many relationship. Django has joined them using obj1_obj2 table and it looks like this in mysql;
id | person_id | nationality_id
-----------------------------------
1 | 1 | 1
2 | 1 | 2
Now when I save obj1 (which shows obj2 in as Multi-select in its form) the ids in the obj1_obj2 table increase even thow I have not changed them. For example I change a basic character field for obj1 on its form and save it and the the data in the joining table appears to be deleted and re-saved giving the entries new ids.
In fact I don't have to change anything all I have to do is save the form and the same thing happens.
All I am doing in the view is form.save(), nothing special. Is that the normal way that it works?
EDIT: Added Models, Views, Forms
class Person(models.Model):
name = models.CharField()
birthdate = models.CharField()
nationality = models.ManyToMany(Nationality)
class Employee(Person):
employeeNum = models.CharField()
class FamilyMember(Person):
employee = models.ForeignKey(Employee)
relationship = models.CharField()
class Nationality(models.Model):
abbrev = models.CharField()
country = models.CharField()
class FamilyMemberDetailsForm(forms.ModelForm):
class Meta:
model = FamilyMemeber
exclude = ['employee']
def editFamilyMember(request, familyMember_id):
familyMember = get_object_404(FamilMember, familyMember_id)
if request.method == 'POST':
form = FamilyMemberDetailsForm(request.POST, instance=familyMember)
if form.is_valid():
form.save()
else:
form = FamilyMemberDetailsForm(instance=familyMember)
return render_to_response(editForm.html, {'form':form},
context_instance(RequestContext(request))
This is a cut down version of the models, but the same thing happens for saving an employee or familyMember. The FamilyMember I have shown because it is as simple as this I create the modelForm and then make changes and then save it. For the employee I do some more manipulation in the init of Form for the Nationality, mainly for presentation, and at first I thought it was this manipulation that was causing it, but as I said the same thing happens with the FamilyMember where I do nothing except save.
The Nationality is presented on the form as a multiselect box with a list and the user can select 1 or more from the list. If I just present the populated form and then save it without changing anything the id for the many-to-many table entry changes.
I have changed the example table titles also.
Thanks,
Andrew
Yes, the deletion of any existing rows in appname_obj1_obj2 is expected behavior when saving a form for an object that has a ManyToManyField.
You can see the clear() before the add(**values) in ReverseManyRelatedObjectsDescriptor and ManyRelatedObjectsDescriptor in django/db/models/fields/related.py.
Pop open a shell and take a look at the queries yourself. Something like this should show you the DELETE before the INSERT in the raw sql.
from django.db import connection
fm = FamilyMember.objects.get(pk=1)
form = FamilyMemberDetailsForm(instance=fm)
data = form.initial
data['name'] = "z%s" % data['name']
form = FamilyMemberDetailsForm(data, instance=fm)
connection.queries = [] # clearing to limit the queries you have to look at
form.save()
for q in connection.queries:
print("%s\n" % q['sql'])