Graphene Django File field get absolute path - django

I have an image field in my Django model and I am trying to get absolute path of the image field output from Graphene so as to connect to my client.
class ProfileType(DjangoObjectType):
class Meta: model = Profile
def resolve_avatar(self, info, **kwargs):
print(info.context.build_absolute_uri(self.avatar))
I do not get an absolute file field path.

If Profile.avatar is ImageField you should use self.avatar.url instead of self.avatar:
info.context.build_absolute_uri(self.avatar.url)

So I got an answer to this and I want to make sure I post it someone else does not make the same mistake.
Here is what the code should look like
class ProfileType(DjangoObjectType):
class Meta:
model = Profile
avatar = graphene.String()
cover_photo = graphene.String()
def resolve_avatar(self, info):
return info.context.build_absolute_uri(self.avatar.url)
def resolve_cover_photo(self, info):
return info.context.build_absolute_uri(self.cover_photo.url)

Related

Add method doesnt work when trying to establish m2m relationships using post_save in Django

My Content model has a many-to-many relationship to the Tag model. When I save a Content object, I want to add the relationships dynamically. I'm doing this the following way.
def tag_content(obj):
for tag in Tag.objects.all():
print tag
obj.tags.add(tag)
obj.is_tagged = True
obj.save()
class Tag(models.Model):
name = models.CharField(max_length=255)
class Content(models.Model):
title = models.CharField(max_length=255)
is_tagged = models.BooleanField(default=False)
tags = models.ManyToManyField(Tag, blank=True)
def save(self, *args, **kwargs):
super(Content, self).save(*args, **kwargs)
#receiver(post_save, sender = Content)
def update_m2m_relationships_on_save(sender, **kwargs):
if not kwargs['instance'].is_tagged:
tag_content(kwargs['instance'])
The tag_content function runs, however, the m2m relationships are not established. Im using Django 1.9.8 btw. This makes no sense. What am I missing? Moreover, if I do something like tag_content(content_instance) in shell, then the tags are set, so the function is ok. I guess the problem is in the receiver. Any help?
Edit
My question has nothing to do with m2m_changed, as I have said, creating a Content object in shell works perfectly. Therefore, the problem lies in the admin panel's setup.
Ok so I solved the problem. Basically, this has something to do with how Django handles its form in the admin panel. When trying to add the Contents from admin, I kept the tags field empty, thinking the tag_content function would handle it. However, that is exactly where the problem was, as creating a Content from shell tagged it just fine. In other words, changing the admin panel to something like this solved my problem :
from django.contrib import admin
from myapp.models import *
from django import forms
class ContentCreationForm(forms.ModelForm):
class Meta:
model = Content
fields = ('title',)
class ContentChangeForm(forms.ModelForm):
class Meta:
model = Content
fields = ('title', 'is_tagged', 'tags')
class ContentAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if obj is None:
return ContentCreationForm
else:
return ContentChangeForm
admin.site.register(Tag)
admin.site.register(Content, ContentAdmin)
When trying to create a new Content, only the 'title' field is presented. This solves the problem.

Default Image in Django Rest Framework

I have an optional ImageField in my model with a default image. I am using Django Rest Framework for the model api. However when I try to post (post request outside the browser) without images I continue getting the error:No file was submitted. Check the encoding type on the form.
models.py
class Detector(models.Model):
average_image = models.ImageField(upload_to='average_image/',
default='average_image/default.png',
null=True, blank=True)
serializer.py
class DetectorSerializer(serializers.ModelSerializer):
class Meta:
model = Detector
fields = ('average_image')
views.py
class DetectorAPIList(generics.ListCreateAPIView):
serializer_class = DetectorSerializer
What am I missing?
Thanks for your time!
i hit the same issue, i had to explicitly mark my image field in the serializer as blank:
class DetectorSerializer(serializers.ModelSerializer):
average_image = serializers.ImageField(source='average_image', blank=True)
class Meta:
model = Detector
fields = ('average_image',)
It seems that rest framework is unable to grab it from model or something. After this i am able to POST data to the API using requests like this:
import requests
from requests.auth import HTTPBasicAuth
r = requests.post(
'http://localhost:8000/detectors/',
data={'some': 'data'},
auth=HTTPBasicAuth('user', 'password')
)
print r.text
And this is the response, as you can see it used the default from the model field definition:
{"average_image": "average_image/default.png"}
You can also try to POST with specified file:
r = requests.post(
'http://localhost:8000/detectors/',
files={'average_image': open('/path/to/image.jpg')},
data={'some': 'data'},
auth=HTTPBasicAuth('user', 'password')
)
print r.text
Hope this helps.

How to not render django image field currently and clear stuff?

I took a look at following SO question, but had no luck. I don't know, maybe I didn't understand the answers.
1) How to remove the “Currently” tag and link of a FileInput widget in Django?
2) Django ModelForm ImageField
My form:
class SettingsForm(forms.ModelForm):
company_logo = forms.ImageField(label=_('Company Logo'),required=False, error_messages = {'invalid':_("Image files only")})
class Meta:
model = Settings
fields = ("company_logo")
....
My model:
class Settings(models.Model):
strg=CustomFileSystemStorage(strict_name='images/company_logo.png',save_format='PNG')
company_logo=models.ImageField(upload_to='images',blank=True,null=True,storage=strg)
.....
After rendering:
I see from the first link, that the models.ImageField inherits the FileInput and adds the extra stuff, but I do not understand how to overcome this?
Thanks in advance.
The solution is:
class SettingsForm(forms.ModelForm):
company_logo = forms.ImageField(label=_('Company Logo'),required=False, error_messages = {'invalid':_("Image files only")}, widget=forms.FileInput)
class Meta:
model = Settings
fields = ("company_logo")
....
I added the widget forms.FileInput, in order to tell the ImageField to use the basic field, not the one inherited from FileInput.
#mtndesign, you might also want a "remove" option, which you can place wherever you like in your template.
class MyForm(forms.ModelForm):
photo = forms.ImageField(required=False, widget=forms.FileInput)
remove_photo = forms.BooleanField(required=False)
...
def save(self, commit=True):
instance = super(MyForm, self).save(commit=False)
if self.cleaned_data.get('remove_photo'):
try:
os.unlink(instance.photo.path)
except OSError:
pass
instance.photo = None
if commit:
instance.save()
return instance
You can change the widget used to render the form field by specifying it on initializing:
class SettingsForm(forms.ModelForm):
company_logo = forms.ImageField(label=_('Company Logo'),required=False, \
error_messages ={'invalid':_("Image files only")},\
widget=FileInput)
See the docs for widgets.

ModelForm which takes either an Image or a URL and saves to an ImageField

I have a model which takes an image in an ImageField:
class Result(models.Model):
image = models.ImageField(upload_to=get_userphoto_upload_path)
I want a form that can take either a URL or an image, and will save the image to the model transparently.
This is what I'm thinking:
class ResultForm(forms.ModelForm):
externalsource = forms.URLField(label='External URL', required=False)
def clean(self):
cleaned_data = super(ResultForm, self).clean()
externalsource = cleaned_data.get('externalsource', False)
if externalsource:
req = requests.get(externalsource)
image = StringIO(req.content)
self.image.save(image)
class Meta:
fields = ['image']
model = Result
I know the self.image.save(image) isn't correct (self.image does not exist) ... That's how I'd save the image manually if it was a Model rather than a Form. I'm not sure what I should use in its place.
I think you'd like to do something like the following. Note, I haven't run it or tested it or anything. But it should set you on the correct path hopefully.
from django.core.files.uploadedfile import InMemoryUploadedFile
class ResultForm(forms.ModelForm):
externalsource = forms.URLField(label='External URL', required=False)
def clean(self):
cleaned_data = super(ResultForm, self).clean()
externalsource = cleaned_data.get('externalsource', False)
if externalsource:
req = requests.get(externalsource)
image = StringIO(req.content)
file = InMemoryUploadedFile(file=image, field_name=None, name=externalsource, content_type=req.content_type, size=req.size, charset=None)
# Oops, long time since I used Forms, don't know how to do FileFields in forms
# but something like you already wrote:
self.image.save(name=dirname(externalsource), content=file)
class Meta:
fields = ['image']
model = Result
So basically, only making an InMemoryUploadedFile and stuffing your image in there, -- and saving that in the ImageField.
Actually you can also simplify and use SimpleUploadedFile().
I also see now that you have another question embedded in there that is about Forms and Models and FileFields, -- I don't remember how to do that. :P

ForeignKey field will not appear in Django admin site

A foreign key on a model is not appearing in the Django admin site. This is irrespective of whether the field is explicitly specified in a ModelAdmin instance (fields = ('title', 'field-that-does-not-show-up')) or not.
I realize there are many variables that could be causing this behavior.
class AdvertiserAdmin(admin.ModelAdmin):
search_fields = ['company_name', 'website']
list_display = ['company_name', 'website', 'user']
class AdBaseAdmin(admin.ModelAdmin):
list_display = ['title', 'url', 'advertiser', 'since', 'updated', 'enabled']
list_filter = ['updated', 'enabled', 'since', 'updated', 'zone']
search_fields = ['title', 'url']
The problem is the advertiser foreign key is not showing up in the admin for AdBase
class Advertiser(models.Model):
""" A Model for our Advertiser
"""
company_name = models.CharField(max_length=255)
website = models.URLField(verify_exists=True)
user = models.ForeignKey(User)
def __unicode__(self):
return "%s" % self.company_name
def get_website_url(self):
return "%s" % self.website
class AdBase(models.Model):
"""
This is our base model, from which all ads will inherit.
The manager methods for this model will determine which ads to
display return etc.
"""
title = models.CharField(max_length=255)
url = models.URLField(verify_exists=True)
enabled = models.BooleanField(default=False)
since = models.DateTimeField(default=datetime.now)
expires_on=models.DateTimeField(_('Expires on'), blank=True, null=True)
updated = models.DateTimeField(editable=False)
# Relations
advertiser = models.ForeignKey(Advertiser)
category = models.ForeignKey(AdCategory)
zone = models.ForeignKey(AdZone)
# Our Custom Manager
objects = AdManager()
def __unicode__(self):
return "%s" % self.title
#models.permalink
def get_absolute_url(self):
return ('adzone_ad_view', [self.id])
def save(self, *args, **kwargs):
self.updated = datetime.now()
super(AdBase, self).save(*args, **kwargs)
def impressions(self, start=None, end=None):
if start is not None:
start_q=models.Q(impression_date__gte=start)
else:
start_q=models.Q()
if end is not None:
end_q=models.Q(impression_date__lte=end)
else:
end_q=models.Q()
return self.adimpression_set.filter(start_q & end_q).count()
def clicks(self, start=None, end=None):
if start is not None:
start_q=models.Q(click_date__gte=start)
else:
start_q=models.Q()
if end is not None:
end_q=models.Q(click_date__lte=end)
else:
end_q=models.Q()
return self.adclick_set.filter(start_q & end_q).count()
class BannerAd(AdBase):
""" A standard banner Ad """
content = models.ImageField(upload_to="adzone/bannerads/")
The mystery deepens. I just tried to create a ModelForm object for both AdBase and BannerAd, and both generated fields for the advertiser. Some crazy admin things going on here...
I believe I've just run into exactly the same problem, but was able to debug it thanks to the help of persistent co-workers. :)
In short, if you look in the raw HTML source you'll find the field was always there - it's just that:
Django tries to be clever and put the form field inside a div with CSS class="form-row $FIELD_NAME",
The field's name was "advertiser", so the CSS class was "form-row advertiser",
...Adblock Plus.
Adblock Plus will hide anything with the CSS class "advertiser", along with a hell of a lot of other CSS classes.
I consider this a bug in Django.
maybe it is an encode error. I had the same problem, but when i added # -- coding: UTF-8 -- in the models.py, all fine.
Another very dumb cause of the same problem:
If there is only one instance of the related model, then the filter simply won't show. There is a has_output() method in RelatedFieldListFilter class that returns False in this case.
It's a strange problem for sure. On the AdBase model if you change
advertiser = models.ForeignKey(Advertiser)
to
adver = models.ForeignKey(Advertiser)
then I believe it'll show up.
Powellc, do you have the models registered with their respective ModelAdmin class?
admin.site.register(Advertiser, AdvertiserAdmin) after the ModelAdmin definitions.
You are talking about the list_display option, right?
Is the unicode-method for your related model set?
If the field is a ForeignKey, Django
will display the unicode() of the
related object
Also check this thread for some hints: Can "list_display" in a Django ModelAdmin display attributes of ForeignKey fields?
Try disabling your ad blocker. No, this is not a joke. I just ran into this exact problem.
We just ran into this problem.
It seems that if you call you field advertiser the in the admin the gets given an 'advertiser' class.
Then is then hidden by standard ad blocking plugins. If you view source your field will be there.