I am using Tweepy to post a tweet from Django admin. How can I retrieve "title" and "image" from the model object as shown in the picture, whenever I click on the tweet button it should post a tweet on my Twitter account with title as text and image.
Example: Suppose I have 4 model objects and each object has a title and an image, I want to get the title and image of only that object which I want to post on Twitter.
One thing I can do is pass a primary key or id of that particular model object
but I don't know how to pass it in my template below.
Django Admin Form page
#template
{% extends 'admin/change_form.html' %}
{% load i18n %}
{% block content %}
{{ block.super }}
<form action="{% url 'post_tweet' %}" method="POST">
{% csrf_token %}
<input type="submit" value="Tweet" name="add_tweet">
</form>
{% endblock %}
#urls.py
urlpatterns = [
path('', views.Home.as_view(), name="home"),
path('$', views.tweet, name="post_tweet"),
]
#models.py
class Movie(models.Model):
GENRE = (
('Action', 'Action'),('Adventure', 'Adventure'),('Comedy', 'Comedy'),
('Crime', 'Crime'),('Drama', 'Drama'),('Fantasy', 'Fantasy'),
('Horror', 'Horror'),('Mystery', 'Mystery'),('Science Fiction', 'Science Fiction'),
('Superhero', 'Superhero'),('Thriller', 'Thriller'),('War','War'),('Others','Others')
)
image = models.ImageField(upload_to="images/",blank=True, default="default-image.png",null=True)
title = models.CharField(max_length=50, unique=True)
slug = models.SlugField(max_length=100, allow_unicode=True, unique=True, default='',blank=True)
genre = models.CharField(max_length=30, choices=GENRE)
description = models.TextField(max_length=500, blank=True)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args,**kwargs)
class Meta:
ordering = ["-title"]
# views.py
def tweet(request):
if request.method == "POST":
twitter_auth_keys = {
"consumer_key" : "XXX",
"consumer_secret" : "XXX",
"access_token" : "XXX",
"access_token_secret" : "XXX"
}
auth = tweepy.OAuthHandler(
twitter_auth_keys['consumer_key'],
twitter_auth_keys['consumer_secret']
)
auth.set_access_token(
twitter_auth_keys['access_token'],
twitter_auth_keys['access_token_secret']
)
api = tweepy.API(auth)
`Do something here`
tweet = "New"
post_result = api.update_status(status=tweet)
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
You can print the object_id value in your template, that value is passed by default by the change_view method, you can always override this method if you want to pass extra data to your change_view template too: https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.change_view
So one way to do what you want to do is this, you can print the object_id in a hidden input so the value will be passed to your view by the form submit:
{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block content %}
{{ block.super }}
<form action="{% url 'post_tweet' %}" method="POST">
{% csrf_token %}
<input type="hidden" name="movie_id" value="{{ object_id }}">
<input type="submit" value="Tweet" name="add_tweet">
</form>
{% endblock %}
Now you can get the instance of the object and get the title and the image of a movie in your tweet view by searching by its id.
Related
Rendered django model object cannot give any output in template. My Code is:
model.py:
class MyModel(models.Model):
address = models.GenericIPAddressField(
max_length=15,
verbose_name=_('address')
)
Path = models.CharField(
max_length=300,
verbose_name='path',
)
activate = models.CharField(max_length=5, default='off', )
views.py:
class MyView(ListView):
model = models.MyModel.objects.all()[0]
template_name = '../on_off.html'
context_object_name = 'obj_list'
admin.py:
class MyAdmin(admin.ModelAdmin):
list_display = ('address', 'Path', )
exclude = ('activate', )
change_list_template = '../on_off.html'
on_off.html:
{% extends 'admin/change_list.html' %}
{% block object-tools %}
{% if obj_list %}
<form id="on_off_status" method="POST">
<label id="onoff" class="switch">
{% csrf_token %}
<input type="checkbox" id="togBtn" value=" {{ obj_list.activate }} ">
<div class="slider round"></div>
</label>
</form>
{% endif %}
...
In Django model, the system accepts only one object and I want to give to toggle switch button value in template using activate field in MyModel model. But it is not rendered in template, I couldn't get any object data even if I try <h1> {{ obj_list }} </h1>, it turns <h1> </h1> . Any help or suggestion appreciated.
Render the field manually
<label id="onoff" class="switch">
{% csrf_token %}
{{ obj_list.activate }}
<div class="slider round"></div>
</label>
Instead of using the views.py, django-admin provide a function named changelist_view(). Now it is working, I deleted the funtion in views.py and I added changelist_view() function to my admin.py looks like:
class MyAdmin(admin.ModelAdmin):
list_display = ('address', 'Path',)
exclude = ('activate',)
change_list_template = '../nfs_on_off.html'
def changelist_view(self, request, extra_context=None):
object = self.model.objects.all()
context={
'obj_list': object,
}
return super(MyAdmin, self).changelist_view(request, context)
I am trying to display a checklist in the CreateView using the values in the ForeignKey fields for descriptions.
models.py
class Structure(models.Model):
name = models.CharField(max_length = 30)
description =models.CharField(max_length = 300, null=True, blank=True)
def __str__(self):
return self.name
class SelectedFramework(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
structure = models.ForegignKey(Structure)
selected = models.BooleanField(default = False)
views.py
class FrameworkCreateView(generic.CreateView):
model = SelectedFramework
fields =['structure', 'selected']
template_name = 'catalogue/structure.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super(FrameworkCreateView, self).form_valid(form)
structure.html
{% extends 'catalogue\base.html' %}
{% block container %}
<h2>{% block title %}Structures{% endblock title %}</h2>
<form action="" method="post">
{% csrf_token %}
{% for field in form %}
<div class="col-sm-10">{{form.structure}} {{form.selected}}</div><br>
{% endfor %}
</div>
</form>
{% endblock %}
The code above works but will display the ForeignKey 'structure' as a dropdown list with the values of __str__. Is there a way to display string for structure.name and structure.description with the checkbox from selected in the CreateView?
In your template use:
{{ form.structure.name }}
{{ form.structure.description}}
You can write custom form, override the save method and create Structure object manually there:
class FrameworkForm(forms.ModelForm):
structure_name = forms.CharField(required=True)
structure_description = forms.CharField(required=False)
class Meta:
model = SelectedFramework
fields = [
'structure_name', 'structure_description', 'selected'
]
def save(self, commit=False):
instance = super(FrameworkForm, self).save(commit=False)
structure = Structure(
name=self.cleaned_data.get('structure_name'),
description=self.cleaned_data.get('structure_description')
)
structure.save()
instance.structure = structure
instance.save()
return instance
Also add form_class = FrameworkForm to your view instead of fields = ['structure', 'selected']
EDIT:
Perhaps you want something like this:
<ul>
{% for structure in form.fields.structure.choices.queryset %}
<li>{{ structure.name }} - {{ structure.description }}</li>
{% endfor %}
</ul>
If you want to get fields by iterating in the template. You have to use-
{% for field in form %}
{{ field }}
{% endfor %}
don't have to use any dot notation to get the field. If you want to get the label of the field you can use {{ field.label}} usually before {{field}}
EDIT: I fixed the views.py with Av4t4r's code but it still shows no content. When I type something in voodoo.html it actually shows content, but all of the content inside the {% block content %} are not showing. Why is that?
Hello I am trying to make a simply gallery app where the first view (listview) is a list of all the persons (which are the objects), and when a user clicks on one it proceeds to the next page with a given pk/id key. But when it comes to that page... the content is blank. Here is what I have:
urls.py:
urlpatterns = [
url(r'^$', ListView.as_view(queryset=Images.objects.all(), template_name='imgboard/home.html')),
url(r'^imgboard/(?P<id>\d+)/$', views.voodoofunction, name='voodoofunction'),
]
views.py (I feel like this is where the problem is):
def voodoofunction(request, id=None):
instance = get_object_or_404(Moreimages, id=id)
context = { "object_list": instance, }
return render(request, "imgboard/voodoo.html", context)
models.py
class Images(models.Model):
name_person = models.CharField(max_length=70)
instagram = models.CharField(max_length=200)
img_url = models.CharField(max_length=500)
def __unicode__(self):
return self.name_person
class Meta:
verbose_name_plural = 'Images'
class Moreimages(models.Model):
key = models.ForeignKey(Images, on_delete=models.CASCADE)
img_url = models.CharField(max_length=500)
def __unicode__(self):
return str(self.key)
class Meta:
verbose_name_plural = "More Images"
listview_code.html
{% block content %}
{% for object in object_list %}
<p>{{object.name_person}}</p>
{% endfor %}
{% endblock %}
voodoo.html:
{% block content %}
<h2>{{ object.name_person}}<br></h2>
<h4>{{object.instagram}}</p></h4>
<br>
{% for object in object_list %}
<p><img src="{{object.img_url}}", width=350, height="360></img>"</p>
{% endfor %}
{% endblock %}
Your context has no "object" in it. And your "object_list" is an instance, not a list (so your for loop is doing nothing).
I'm trying to display a django ModelForm in my template, but I could not get it to work.
Here is my code:
the template is this:
{% extends 'base.html' %}
{% load i18n %}
{% load url from future %}
{% block content %}
{{ block.super }}
<section>
<article>
<form action="{% url 'SaisirEnfant' %}" method="post">{% csrf_token %}
<fieldset>
<div id="newad"> {{ newenfant.as_p }} </div>
<div id="sub"> <input type="submit" value="Submit" /> </div>
</fieldset>
</form>
</article>
</section>
{% endblock %}
and the models are like this:
class PersonneAdulte(models.Model):
profile = models.ForeignKey(Profile, verbose_name='Personne Adulte')
prenom = models.CharField(max_length=50)
responsable = models.BooleanField(default=False, verbose_name=_('responsable'))
class Famille(models.Model):
responsable = models.ForeignKey(PersonneAdulte, verbose_name='responsable')
sous_responsable = models.IntegerField(null=True, blank=True)
coef_fam = models.IntegerField(null=True, blank=True)
id_fam = models.IntegerField(null=True, blank=True)
class Enfant(models.Model):
responsable = models.ForeignKey(Famille, verbose_name='responsable')
nom = models.CharField(max_length=50 )
finaly the wiews is like this:
class PersonneAdulteForm(ModelForm):
class Meta:
model = PersonneAdulte
exclude = ('profile')
def PersonneAdulte(request):
if request.method == 'POST':
adulte = PersonneAdulteForm(request.POST)
if adulte.is_valid():
#creates a new `User`.
new_user = UserenaSignup.objects.create_user(username=adulte.data['nom'],
email='nom.prenom#site.fr',
password='0000',
active=False,
send_email=False)
# Send the signup complete signal
userena_signals.signup_complete.send(sender=None,
user=new_user)
#Activate a user with an activation key.
activation_key = UserenaSignup.objects.get(user_id=new_user.id).activation_key
user = UserenaSignup.objects.activate_user(activation_key)
t = adulte.save(commit=False)
if t.responsable == False :
new_user.is_active = False
new_user.save()
else :
f = Famille.objects.create(pk=new_user.id, responsable_id=new_user.id, id_fam=new_user.id)
p = adulte.save(commit=False)
p.id = p.profile_id = new_user.id
p.save()
return HttpResponse( 'id: ' + str(p.id) )
else:
adulte = PersonneAdulteForm()
return render_to_response('familles/PersonneAdulte.html', dictionary={ 'adulte' : adulte}, context_instance=RequestContext(request))
Profile is the model defined by the userena package
My view is for creating a new Enfant instance but no data at all is displayed and there is no error message. The problem is related to the foreign key in my model (responsable) because if I exclude the field in my form it works fine. Anybody knows where this problem comes from or how I can debug it?
I am trying to create a simple CRUD with ModelForm. It works fine except that every time I edit, saving creates a new instance of the data. So i edit and get an extra row in DB instead of an updated one. I am at a loss as to how it knows to save an existing charity as it does not store the PK (id) as a hidden field in the form. That is how I always did it before trying to use the 'fabulous' ModelForm!
It's driving me nuts, I have read everything and as far as I can tell I am doing everything right.
Here is my code..
Model:
from django.db import models
from django.conf import settings
COUNTRY_CHOICES = settings.COUNTRIES
class Charities(models.Model):
charity_name = models.CharField(max_length=100)
country = models.CharField(max_length=4, choices=COUNTRY_CHOICES)
registration_number = models.CharField(max_length=100)
address1 = models.CharField(max_length=100)
address2 = models.CharField(max_length=100)
city = models.CharField(max_length=30)
zip = models.CharField(max_length=10)
phone = models.CharField(max_length=20)
email = models.EmailField()
charity_logo_image = models.CharField(max_length=100)
charity_banner_image = models.CharField(max_length=100)
charity_accepted = models.IntegerField()
def __str__(self):
return self.charity_name
def __unicode__(self):
self.charity_name
View:
def list(request):
charities = Charities.objects.all()
return render_to_response('charities_charity_list.html', {'charities': charities})
def add(request):
return add_or_edit(request)
def edit(request, charity_id):
return add_or_edit(request, charity_id)
def add_or_edit(request, charity_id=None):
print "ID = " + str(charity_id)
form = CharityForm(request.POST or None,
instance=charity_id and Charities.objects.get(pk=charity_id))
# Save new/edited student
if request.method == 'POST' and form.is_valid():
print form
form.save()
return HttpResponseRedirect('/charities/list/')
return render_to_response('charities_charity_edit.html', {'form': form})
Form:
class CharityForm(ModelForm):
class Meta:
model = Charities
Template:
{% extends "base.html" %}
{% block title %}Charities Add{% endblock %}
{% block content %}
<form method="post" action="/charities/add/" id="save"><table cellpadding="0">{{ form.as_table}}</table><input type="submit" value="Save"></form>
{% endblock %}
It doesn`t work because your template is always POSTing to the view that adds a new Charity. When you manually type a URL like /charities/edit/5, it creates the ModelForm with the right initial data, but then POSTs to /charities/add, thus creating a new instance. You need to POST to /charities/edit/5, for example. Take a look at the url template tag.
I suggest you use 2 templates, one for adding, another for editing. I know it may not be very DRY, but I believe it's clearer this way.
Add template:
{% extends "base.html" %}
{% block title %}Charities Add{% endblock %}
{% block content %}
<form method="post" action="{% url charities_app.views.add %}"><table cellpadding="0">{{ form.as_table}}</table><input type="submit" value="Save"></form>
{% endblock %}
Edit template:
{% extends "base.html" %}
{% block title %}Edit Charity{% endblock %}
{% block content %}
<form method="post" action="{% url charities_app.views.edit charity.id %}"><table cellpadding="0">{{ form.as_table}}</table><input type="submit" value="Save"></form>
{% endblock %}
You may also want to check the create_object and update_object generic views, they are very useful in simple cases like yours.