I am trying to run a system command with the value of a field from a queryset but not having much luck. And it is returning 'Jobs' object is not subscriptable'. Please see below for relevant information.
Models.py
class Jobs(models.Model):
user_id = models.CharField(max_length=100)
template = models.CharField(max_length=100)
change_ref = models.CharField(max_length=100)
summary = models.CharField(max_length=100)
category = models.CharField(max_length=100)
Views
def delete_job(request, job_id):
record = Jobs.objects.get(pk=int(job_id))
os.system('mkdir /home/username/' + record['summary'])
return HttpResponseRedirect("/configen")
I am passing the job_id in through the URL which seems to work fine ( I can delete the record no problem). I was under the impression the 'get' would simply get one record, which I could then reference as a dictionary?
I'm sure there is a simple solution, it doesn't seem to work with string formatting either (using %s or .format()) methods.
Thank you in advance
You're correct that get does get one record, but wrong that you can reference it as a dictionary. It's a model instance, so you use the normal dot notation: record.summary.
Related
I have the following model:
class ShoppingList(models.Model):
name = models.CharField(max_length=100, default='Main')
owners = models.ManyToManyField(User, through='ListOwner')
class ListOwner(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
shopping_list = models.ForeignKey(ShoppingList, on_delete=models.CASCADE)
is_main_owner = models.BooleanField(default=False)
Next, I'm trying to query ShoppingList for the current user.
I used this https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships as an example.
I expected that right way to do it is to use this construction:
#login_required
def index(request):
shopping_list = ShoppingList.objects.filter(owners__user=request.user)\
.order_by('id').first()
# something else
but in this case, I get an error: Related Field got invalid lookup: user
Everything works fine if use listowner instead of owner in filter() function like this:
shopping_list = ShoppingList.objects.filter(listowner__user=request.user)\
.order_by('id').first()
Can anybody please explain to me why the first one isn't working (while it is recommended to use it in Django documentation)?
The reason it does not work is because the ManyToManyField refers to the User model, hence:
ShoppingList.objects.filter(owners=…)
expects a User, the lookup __user is invalid, since you are already filtering on a user, and the User model has no user field, or a relation named user.
You thus can filter with:
shopping_list = ShoppingList.objects.filter(
owners=request.user
).order_by('id').first()
An alternative is to join on the through model yourself. You then first go through the relation to the ListOwner by using the ForeignKey relation in reverse. You do that by specifying the related_query_name=… parameter [Django-doc], which by default is the name of the model in lowercase. This is what you did in your second solution.
Let's say I have a model Issue that looks like this:
class Issue(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
text = models.TextField()
And another one called Comment like so:
class Comment(models.Model):
issue = models.ForeignKey(Issue)
text = models.TextField()
number = models.AutoField()
I want the comment number field to be relative to the issue.
Which means that every issue will have its separate comment#1, comment#2, comment#3...etc.
Can this be done in Django?
If you removed the number field from your Comment model and replaced it with a date_added field, you could still query the DB to pull all comments associated with a certain entry in order.
class Comment(models.Model):
issue = models.ForeignKey(Issue)
text = models.TextField()
date_added = models.DateField(auto_now_add = True)
Then if you wanted to get all of the comments associated with a certain issue:
i = Issue.object.get(pk=1) #pk = primary key id for whatever issue you want
comments_by_issue = i.comment_set.all().order_by('date_added')
Now you have some comments that you can refer to by index location (comments_by_issue[0] would get you the first comment attached to the issue, for instance).
That index location is the closest way I can figure to get what you're looking for. Someone else mentioned comment.id, but this is just going to be an autoincrementing integer that goes up for every comment. The fifth comment added to your system might have comment.id = 5, but it might be the first comment attached to issue 2 - if I'm reading your query right, having the comment ID doesn't help in that context.
This is more of a workaround than a direct answer, but I hope it helps.
I prefer soundeux's solution. That said, here is the idea...
class Comment(models.Model):
# ...
number = models.PositiveIntegerField(default=1)
def save(self, *args, **kwargs):
obj = super(Comment, self).save(*args, **kwargs)
try:
last_comment = self.issue.comment_set.all().orderby('-number')[0]
except KeyError: # I think it's KeyError... for when there is no comments
pass
else:
Comment.objects.filter(id=self.id).update(number=last_comment.number+1)
return obj
Be careful - this will not be executed when Comments are being updated using the ORM's update method. Indeed, that's what I've used to avoid recursion (which is not a very good solution either). You might wanna implement it as a pre_save event instead of the save() (still won't respond to the update(), but will be more robust about potential recursion problems).
i have following models
class tags(models.Model):
tag = models.CharField(max_length=15) # Tag name
tagDescription = models.TextField() # Tag Description
tagSlug = models.TextField() # Extra info can be added to the existing tag using this field
class stores(models.Model):
storeName = models.CharField(max_length=15) # Store Name
storeDescription = models.TextField() # Store Description
storeURL = models.URLField() # Store URL
storePopularityNumber = models.IntegerField(max_length=1) # Store Popularity Number
storeImage = models.ImageField(upload_to=storeImageDir) # Store Image
storeSlug = models.TextField() # This is the text you see in the URL
createdAt = models.DateTimeField() # Time at which store is created
updatedAt = models.DateTimeField() # Time at which store is updated
storeTags = models.ManyToManyField(tags)
class tagsAdmin(admin.ModelAdmin):
list_display = ('tag', 'tagDescription', 'tagSlug')
class storesAdmin(admin.ModelAdmin):
list_display = ('storeName','storeDescription','storeURL',
'storePopularityNumber','storeImage',
'storeSlug','createdAt','createdAt','storeTags'
)
admin.site.register(tags,tagsAdmin)
admin.site.register(stores,storesAdmin)
Whenever I am trying to run command : python manage.py syncdb
I got the error: django.core.exceptions.ImproperlyConfigured: 'storesAdmin.list_display[8]', 'storeTags' is a ManyToManyField which is not supported.
I don't understand what I am doing wrong here. I want to simply display all the models in the django admin site.
You can't reference a Many2ManyField like that, you have to use a method instead in the stores class that looks like this
def get_tags():
return self.storeTags.all()
and reference that in your list_display(...'get_tags')
This is done because the M2M field would result in lots of SQL queries that would slow the entire thing down so therefore the choice would have to come from the developer and not from the framework.
Please check:
ModelAdmin.list_display
"ManyToManyField fields aren’t supported, because that would entail executing a separate SQL statement for each row in the table. If you want to do this nonetheless, give your model a custom method, and add that method’s name to list_display. (See below for more on custom methods in list_display.)"
You can use a custom method to show values of ManyToManyField or simply remove storeTags from list_display
I have in my view comments and I want to sort them with the latest comment at the top of the list. However it is not working. I get this error.
Caught TypeError while rendering: 'Comment' object is not iterable
I am not so sure what is causing this problem. Here is my views and model which may help.
Views
def home(request):
comments = Comment.objects.latest('datetime')
return render_to_response('home.html', {'comments':comments}, context_instance=RequestContext(request))
models
class Comment(models.Model):
name = models.CharField(max_length = 40)
datetime = models.DateTimeField(default=datetime.now)
note = models.TextField()
def __unicode__(self):
return unicode(self.name)
The cleanest way is to add a class meta to your model and add the ordering parameter like this:
class Comment(models.Model):
name = models.CharField(max_length = 40)
datetime = models.DateTimeField(default=datetime.now)
note = models.TextField()
class Meta:
ordering = ['-datetime']
def __unicode__(self):
return unicode(self.name)
So every query you make will be ordered by datetime.
Another advice do not choose "datetime" as a field name, datetime is a python module included in the standard lib.
Also see Django ordering docs here.
The latest method returns only one object, not an iterator:
https://docs.djangoproject.com/en/dev/ref/models/querysets/#latest
Use the order_by method to order them by date (first example in the doc):
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.order_by
Comment in comments = Comment.objects.latest('datetime') is NOT a collection of comment; it is a single comment.
What you want to do is create an array of Comment objects and iterate through that.
class Message(models.Model):
subject = models.CharField(max_length=100)
pub_date = models.DateTimeField(default=datetime.now())
class Topic(models.Model):
title = models.CharField(max_length=100)
message = models.ManyToManyField(Message, verbose_name='Discussion')
I want to get order all the topics according to the latest message object attached to that topic.
I executed this query but this does not give the distinct queryset.
>> Topic.objects.order_by('-message__pub_date').distinct()
You don't need distinct() here, what you need is aggregation. This query will do what you want:
from django.db.models import Max
Topic.objects.annotate(Max('message__pub_date')).order_by('-message__pub_date__max')
Though if this is production code, you'll probably want to follow akaihola's advice and denormalize "last_message_posted" onto the Topic model directly.
Also, there's an error in your default value for Message.pub_date. As you have it now, whenever you first run the server and this code is loaded, datetime.now() will be executed once and that value will be used as the pub_date for all Messages. Use this instead to pass the callable itself so it isn't called until each Message is created:
pub_date = models.DateTimeField(default=datetime.now)
You'll find the explanation in the documentation for .distinct().
I would de-normalize by adding a modified_date field to the Topic model and updating it whenever a Message is saved or deleted.