I don't know how to get data and fill into my word template. It's actually a long list, and I need to fill it on my table on word document. Am I doing it right? Here is my code:
views.py
def save_sample_details(request):
sample = SampleList.objects.all()
doc = DocxTemplate("lab_management/word/sample_template.docx")
context = {
'SNAME' : sample.sample_name,
'STYPE' : sample.sample_type,
'HVER' : sample.hardware_version,
'SVER' : sample.software_version,
'CS' : sample.config_status,
'NUM' : sample.number,
'SNUM' : sample.sample_number,
}
doc.render(context)
doc.save('lab_management/word/sample.docx')
return redirect('/lab/sample/details/')
models.py
class SampleList(models.Model):
sample_name = models.CharField(max_length=32)
sample_type = models.CharField(max_length=32)
hardware_version = models.CharField(max_length=32)
software_version = models.CharField(max_length=32)
config_status = models.CharField(max_length=18)
number = models.IntegerField(default=0)
sample_number = models.CharField(max_length=17)
So if I run this, it shows
'QuerySet' object has no attribute 'sample_name' etc.
You're getting all SampleList objects when you call SampleList.objects.all() so this is returning a QuerySet of zero or more objects, rather than a single object - which is what you want.
Instead you should get the single SampleList object you want: for example sample = SampleList.objects.get(id=1) or another example - to get the first object in the QuerySet you could do sample = SampleList.objects.all()[0] (but if the QuerySet is empty you'll get an index error). You didn't specify how you want to determine which SampleList to put in the Word doc, but you can specify any filters in the .get() properties.
Django has some pretty good documentation covering querysets:
https://docs.djangoproject.com/en/4.1/ref/models/querysets/
Change your code as:
def save_sample_details(request):
sample_list = SampleList.objects.all()
doc = DocxTemplate("lab_management/word/sample_template.docx")
context_list = []
for sample in sample_list:
context = {
'SNAME' : sample.sample_name,
'STYPE' : sample.sample_type,
'HVER' : sample.hardware_version,
'SVER' : sample.software_version,
'CS' : sample.config_status,
'NUM' : sample.number,
'SNUM' : sample.sample_number,
}
context_list.append(context)
doc.render(context_list)
doc.save('lab_management/word/sample.docx')
return redirect('/lab/sample/details/')
You should be iterating in the context_list in the doc as well.
(Assuming you are using docxtpl library)
I have answered my question. Thank you for the help!
views.py
def save_sample_details(request):
sample = SampleList.objects.all()[0:15]
template = DocxTemplate("lab_management/word/sample_template.docx")
context = {
'headers' : ['SNAME', 'STYPE', 'HVER', 'SVER', 'CS', 'NUM', 'SNUM'],
'list': [],
}
alist = ['a']
for i in alist:
for samples in sample:
content= [samples.sample_name, samples.sample_type, samples.hardware_version,
samples.software_version, samples.config_status, samples.number,
samples.sample_number ]
context['list'].append(content)
template.render(context)
template.save('lab_management/word/sample.docx')
return redirect('/lab/sample/details/')
sample_template.docx
Related
I want to insert a ManyToMany fields in my db using django.I select some customers using checkboxes.
This is my models.py :
class Campaign(models.Model):
title = models.CharField(max_length=255)
channel = models.CharField(max_length=255)
start_date = models.DateField()
end_date = models.DateField()
target_prospect = models.ManyToManyField(ProspectClient,related_name='campaigns_prospect')
target_partner = models.ManyToManyField(PartnerClient,related_name='campaigns_partners')
I try the code below in my views.py but didn't work :
def campaigns_page(request):
if request.user.is_authenticated:
if request.user.profile == 'D' or request.user.profile == 'E' or request.user.is_superuser:
campaigns = Campaign.objects.all()
prospects = ProspectClient.objects.all()
partners = PartnerClient.objects.exclude(id__in=PartnerClient.objects.values('id')).all()
context = {
'campaigns':campaigns,
'prospects':prospects,
'partners':partners
}
if request.method == 'POST':
title = request.POST['title']
channel = request.POST['channel']
start_date = request.POST['start_date']
end_date = request.POST['end_date']
descriptions = request.POST['goals'].split(",")
targets = request.POST['targets']
campaign = Campaign.objects.create(title=title,channel=channel,start_date=start_date,end_date=end_date)
for description in descriptions:
goal = Goal.objects.create(description=description)
goal.campaign.add(campaign)
for target in targets:
prospects.campaign.add(campaign)
partners.campaign.add(campaign)
return render(request,'CampaignManagement/campaigns_page.html',context)
return render(request, 'Login/logout.html')
If I delete the part of tergets it works.
But with this part it gives me This error : 'QuerySet' object has no attribute 'campaign'
How I can solve this ?
I see a couple of errors. Perhaps one or more are leading to the problem.
One
Try printing this:
partners = PartnerClient.objects.exclude(id__in=PartnerClient.objects.values('id')).all()
print(partners)
I suspect it will print None since you are excluding all id's in PartnerClient.objects.values('id'). On another note you don't need the all() since exclude() will return all the results you are looking for.
Two
In the line for target in targets: what exactly are you iterating through? targets = request.POST['targets'] is just giving you a string, so it would iterate through each letter. Perhaps you meant:
targets = request.POST['targets'].split(", ")
like you did for descriptions? Or perhaps you are getting a list of items from your form, in which case you can use:
targets = request.POST.getlist('targets')
I want to use nested values inside Mongodb and from the documentation i understand this is done through Embedded documents. If there are any other ways please tell me.
I have the current code:
class compute_instances_subtype(EmbeddedDocument):
label_name = StringField()
class Post(Document):
title = StringField(max_length=120, required=True)
author = StringField(required=True)
tags = ListField(StringField(max_length=30))
compute_instances = ListField(EmbeddedDocumentField(compute_instances_subtype))
post = Post(title="Quora rocks", author="Ross", tags=['tutorial', 'how-to'])
add_test0_label = compute_instances_subtype()
add_test0_label.title = "test0"
add_test0_label.label_name= "value"
add_test1_label= compute_instances_subtype()
add_test1_label.title = "test1"
add_test1_label.label_name= "value"
post.compute_instances.append(add_test0_label)
post.compute_instances.append(add_test1_label)
post.save()
But my issue is that the document does not have a name for the Objects of the compute_instances field, it just says 0 and 1:
id : 60fec94dbb81d98abb557523
title : Quora rocks
author : Ross
tags : compute_instances : Array
0 : Object
label_name : value
1 : Object
label_name : value
I want to have 0 named test0 and 1 named test1.
Please guide me on how to achieve that.
Best regards
It's unclear what you use to print the object, but here are a few comments that might help you:
your compute_instances_subtype class has no title field that is set, so when you set add_test0_label.title = "test0", it's just added to the python object but it's not being saved in the database when you call .save().
0 and 1 that you see in your output are the indexes of the Object in the compute_instances array
Here is a simplified example that might also be helpful:
class ComputeInstancesSubtype(EmbeddedDocument):
label_name = StringField()
title = StringField()
class Post(Document):
title = StringField(max_length=120, required=True)
compute_instances = ListField(EmbeddedDocumentField(ComputeInstancesSubtype))
nested1 = ComputeInstancesSubtype(title='something0', label_name='test0')
nested2 = ComputeInstancesSubtype(title='something1', label_name='test1')
post = Post(title="Quora rocks", compute_instances = [nested1, nested2])
post.save()
print(Post._get_collection().find_one()) # print it in its raw format
returns
{'_id': ObjectId('61071c5e3686c4066dadbc05'),
'title': 'Quora rocks',
'compute_instances': [{'label_name': 'test0', 'title': 'something0'},
{'label_name': 'test1', 'title': 'something1'}]
}
Given the following model:
class Team(models.Model):
name = models.CharField(max_length=50)
others = DictField()
And the following code:
bahia = Team()
bahia.name = "E.C. Bahia"
bahia.others = {"title": "Ninguém nos Vence em Vibração!!!"}
bahia.save()
vicetoria = Team()
vicetoria.name = "E.C. Vicetoria"
vicetoria.others = {"title": "Vice de tudo!"}
vicetoria.save()
I want to find the object that have the word vence, (case insensitive) contained in title value of the field others.
I tried something like:
teams = Team.objects.filter(others__title__icontains="vence")
that gives me the following error:
FieldError: Join on field 'others' not permitted. Did you misspell 'title' for the lookup type?
I also already tried:
teams = Team.objects.filter(others__icontains={"title":"vence"})
that returns None and I know there is at least one collection as result.
SOLUTION:
teams = Team.objects.raw_query({"others.title": {"$regex" : "vence", "$options": "i"}})
The i option makes the search insensitive.
I believe (correct me if I'm wrong) that djangotoolbox DictField doesn't support icontain.
To filter the Dict Field you need to do something like:
Team.objects.raw_query({'title': { $regex : /vence/i } })
Check out this answer: How do I filter based on dict contents in a DictField on a model using the Django-MongoDB Engine?
This answer shows how to do case insensitive mongodb queries: How do I make case-insensitive queries on Mongodb?
I have two collections ScenarioDrivers and ModelDrivers which has One to Many relationship with each other.
class ScenarioDrivers(Document):
meta = {
'collection': 'ScenarioDrivers'
}
ScenarioId = ReferenceField('ModelScenarios')
DriverId = ReferenceField('ModelDrivers')
DriverCalibrationMethod = StringField()
SegmentName = StringField()
DriverValue = ListField()
CalibrationStatus = StringField()
AdjustedValues = ListField(default=[])
CreateDate = DateTimeField(default=ObjectId().generation_time)
LastUpdateDate = DateTimeField(default=datetime.utcnow())
class ModelDrivers(Document):
meta = {
'collection': 'ModelDrivers'
}
PortfolioModelId = ReferenceField('PortfolioModels')
DriverName = StringField()
CreateDate = DateTimeField(default=ObjectId().generation_time)
LastUpdateDate = DateTimeField(default=datetime.utcnow())
FieldFormat = StringField()
DriverData = ListField()
My query is like this.
class GetCalibratedDrivers(Resource):
def get(self, scenario_id):
scenario_drivers_list = []
scenario_drivers = ScenarioDrivers.objects(ScenarioId=scenario_id).exclude('ScenarioId').select_related(1)
for scenario_driver in scenario_drivers:
scenario_driver_dict = {
'id': str(scenario_driver.id),
'DriverId': str(scenario_driver.DriverId.id),
'SegmentName': scenario_driver.SegmentName,
'CalibrationMethod': scenario_driver.DriverCalibrationMethod,
'CalibratedValues': exchange(scenario_driver.DriverValue),
'AdjustedValues': scenario_driver.AdjustedValues,
'LastUpdateDate': formatted_date(scenario_driver.LastUpdateDate),
'FieldFormat': scenario_driver.DriverId.FieldFormat
}
scenario_drivers_list.append(scenario_driver_dict)
return {
'DriverCalibrations': scenario_drivers_list
}
The Query matches 1140 records and then I construct a dictionary and make it a list.
But this API call takes 30s to process just 1140 records. Where I am missing? Please help. I am using latest version of Pymongo and MongoEngine.
I think the problem is not with your query, it is with you looping over 1140 records. I do not see any use of referenced objects so you should consider removing select_related(1). Once you do that, if you want to convert reference object ids to string, you can use as_pymongo() which will do that by default for you. And finally if you must read some data in specific format like formatted_date or exchange, it is better to save them as part of your document. i.e. save FormattedLastUpdateDate with LastUpdateDate. In MongoDB, you have to think about your read specific logic when you save the document.
I'm writing a python script to populate a mongodb database, my models look like the following:
from mongoengine import *
from mongoengine.django.auth import User
class TrackGroup (Document):
name = StringField(required=True)
users = ListField(ReferenceField('User'))
devices = ListField(ReferenceField('Device'))
class Device(Document):
name = StringField(max_length=50, required=True)
grp = ListField(ReferenceField(TrackGroup))
class User(User):
first_name = StringField(max_length=50)
last_name = StringField(max_length=50)
grp = ListField(ReferenceField(TrackGroup))
And my script goes like this:
#Create a group
gName = 'group name'
g = TrackGroup(name=gName)
g.users = []
g.devices = []
g.save()
#create a user
u = User.create_user(username='name', password='admin', email='mail#ex.com')
gRef = g
u.grp = [gRef, ]
u.first_name = 'first'
u.last_name = 'last'
u.save()
gRef.users.append(u)
gRef.save()
#create a device
dev = Device(name='name').save()
gRef = g
dev.grp = [gRef, ]
dev.save()
gRef.devices.append(dev)
gRef.save() #Problem happens here
The problem happens when I call gRef.save() I get the following error:
raise OperationError(message % unicode(err))
mongoengine.errors.OperationError: Could not save document (LEFT_SUBFIELD only supports Object: users.0 not: 7)
I looked around for a while, and here it says that this means I'm trying to set a filed with an empty key, like this: (The example is from the link above, not mine)
{
"_id" : ObjectId("4e52b5e08ead0e3853320000"),
"title" : "Something",
"url" : "http://www.website.org",
"" : "",
"tags" : [ "international"]
}
I don't know where such a field can come from, but I opened a mongo shell and looked at my documents from the three collections, and I couldn't find such a field.
Note: If I add the device first, the same error occurs while saving the group after adding the user.
I had the same error, and this trick work for me:
the_obj_causing_error.reload()
/* make some change */
the_obj_causing_error.price = 5
the_obj_causing_error.save()
just try reload() the object before changing it.