2012-09-25 76 views
0

我正在嘗試獲取與用戶關聯的圖像以正確顯示。我需要幫助確定應包含在模板中的內容。具體而言,我認爲模板「{{review.user__image}}中的代碼是不正確的。根據特定審閱和撰寫該審閱的用戶,我如何提取與用戶相關的圖像?如何拉取與模板中的用戶關聯的屬性?

views.py中

def view_reviews(request, product_name): 
    product = get_object_or_404(Productbackup, url_friendly=product_name) 
    product_id = product.id 
    reviews = Reviewbackup.objects.filter(product_id=product_id).order_by("-created_on") 
    return render_to_response('reserve/templates/view_reviews.html', {'reviews':reviews}, 
     context_instance=RequestContext(request)) 

models.py

class Reviewbackup(models.Model): 
    review = models.CharField('Review', max_length = 2000) 
    user = models.CharField('Username', max_length = 200) 
    rating = models.IntegerField(max_length=2, choices=RATING_OPTIONS) 
    product = models.ForeignKey(Productbackup) 
    def __unicode__(self): 
     return self.review 

class UserProfile(models.Model): 
    user = models.ForeignKey(User, primary_key=True) 
    image = models.ImageField(blank=True, null=True, max_length=255, upload_to="images/") 

模板

{% for review in reviews %} 
    <br><a href = "/user/{{review.user}}/">{{review.user}}</a><br> 
    <img class = "thumbnail" src = "http://test.webfactional.com/static/{{review.user__image}}"><br> 
    {{review}} 
{% endfor %} 

回答

1

對不起,很長的答案。根據你的代碼判斷,我認爲你是Django的新手,所以這個答案希望能夠在過程回答問題中提供信息。

用戶

在您的審查模式,user應該是ForeignKey而不是CharField。我知道存儲用戶名似乎更自然,特別是如果你自己查看數據庫表,但是這種方法很容易出錯,除非你有一個很好的理由,這是一件壞事。

想象一下,你有一個用戶名爲foousername的用戶。然後,該用戶創建一些評論。所以在這一點上,你將有幾個評論user字段將foousername。現在,如果用戶想要將其用戶名更改爲someotherfoousername,爲了不中斷評論和用戶之間的鏈接,您必須更改user字段,以查看用戶爲使用新用戶名而創建的所有評論。這是一個額外的步驟,您可能會忘記這麼做,因此很容易出錯。使用ForeignKey馬上解決這個問題。即使用戶更改他/她的用戶名,用戶的主ID也不會改變,因此如果評論鏈接到主鍵(這是外鍵),則評論不必更新。所以少工作,更可靠的方法。

所以做這個(將解釋接下來related_name):

user = models.ForeignKey(User, related_name='reviews') 

related_name

當您使用related_name,Django的使你的生活變得更加簡單。

考慮你的看法。首先你查詢產品。然後,一旦你得到它,你把它的ID,然後你構建一個查詢,將返回該產品的所有評論。使用Django,你可以使用更少的代碼來完成所有這些。

product = get_object_or_404(Productbackup, url_friendly=product_name) 
reviews = product.reviewbackup_set.all() 

但是,由於整個_set業務,這是有點令人困惑。這是related name進來如果你定義product領域如下:

product = models.ForeignKey(Productbackup, related_name='reviews') 

,那麼你可以做同樣的多一點可讀的方式(和Python應該是可讀的...):

reviews = product.reviews.all() 

用戶的配置文件

外鍵允許實現一對多的關係。所以對於產品和評論來說,這是非常合理的。一個產品可以有很多評論。但通常情況下,用戶配置文件並非如此。通常用戶只有一個用戶配置文件。所以,你的用戶配置文件中,你不應該有ForeignKey給用戶,而是應該用OneToOneField像這樣:

user = models.OneToOneField(User, primary_key=True, related_name='profile') 

這可讓您輕鬆訪問用戶的個人資料:

user_profile = User.objects.get(...).profile 

用戶的圖像

對於每一個審查,現在因爲我的第一個解釋用戶是ForeignKey,您可以非常容易地訪問用戶的圖像:

review = Reviewbackup.objects.all()[0] 
user_image = review.user.profile.image # <- see, very easy 

圖片URL

每當你在Django使用FileField,它上傳文件到在你的媒體文件夾upload_to的地方 - 在您的項目設置中MEDIA_ROOT定義的。所以在你的情況下,Django會將圖像存儲在媒體文件夾中的images文件夾中。此外,如果您配置MEDIA_URL,允許訪問像文件的URL:

user_profile.image.url 

硬編碼網址

它是一種非常糟糕的主意,包括您的模板中直接的網址。那是什麼url模式名稱。所以這個想法是,你分配給url模式一個名字,以便你以後通過引用一個名字來獲得url。這使得代碼更易於維護。例如,下面是一個網址模式供用戶:

url(r'^user/(?P<username>\w+)/$', 'user_view', name='user_view') 

這使您可以在模板中使用它,像這樣:

{% load url from future %} 
link: <a href="{% url 'user_view' username=user.username %}">{{ user.username }}</a> 

將所有內容放在一起

# views.py 
def view_reviews(request, product_name): 
    product = get_object_or_404(Productbackup, url_friendly=product_name) 
    reviews = product.reviews.all().order_by("-created_on") 
    return render_to_response('reserve/templates/view_reviews.html', 
           {'reviews':reviews}, 
           context_instance=RequestContext(request)) 

# models.py 
class Reviewbackup(models.Model): 
    review = models.CharField('Review', max_length = 2000) 
    user = models.ForeignKey(User, related_name='reviews') 
    rating = models.IntegerField(max_length=2, choices=RATING_OPTIONS) 
    product = models.ForeignKey(Productbackup, related_name='reviews') 
    def __unicode__(self): 
     return self.review 

class UserProfile(models.Model): 
    user = models.OneToOneField(User, primary_key=True, related_name='profile') 
    image = models.ImageField(blank=True, null=True, max_length=255, upload_to="images/") 

一個d

{# template #} 
{% load url from future %} 
{% for review in reviews %} 
    <br><a href="{% url user_view username=review.user.username %}"> 
     {{ review.user.username }}</a><br> 
    <img class="thumbnail" src="{{ review.user.profile.image.url }}"><br> 
    {{ review.review }} 
{% endfor %} 
+0

感謝您的全面回答!當我將用戶從CharField更改爲ForeignKey時,當我運行遷移時(我正在使用South)時出現錯誤:以下SQL查詢失敗:CREATE INDEX「reserve_reviewbackup_fbfc09f1」ON「reserve_reviewbackup」(「user_id」); 錯誤是:索引reserve_reviewbackup_fbfc09f1已經存在 !在實際遷移過程中發現錯誤!中止。 !由於您的數據庫不支持運行 !交易中的模式變更聲明,我們有 !使其處於移民之間的臨時狀態。 – sharataka

+0

很抱歉聽到這個消息。不知道如何解決它。在數據庫中有多少數據?如果開發數據庫/部署,則可以從頭開始(從頭開始執行syncdb),確保新的數據庫模式正常工作,然後在所有調試和錯誤修復後遷移舊數據。 – miki725

-1

image不在User,它在UserProfile

{{ review.user.userprofile.image }} 
+0

我試過{{review.user.userprofile.image}}但它不工作。 – sharataka

0

看起來像你不知道如何獲得你的用戶配置文件。下面是關於如何定義用戶配置,因此將工作的一些信息:

https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users

總之,你會成爲一個UserProfile.user OneToOneField,然後你可以使用user.get_profile( )。否則,您可以保留模型定義,並使用UserProfile.objects.get(user=user)user.userprofile_set.all()[0](eww)。

一旦你有你的UserProfile對象,@Ignacio是非常正確的。圖像在那裏。我懷疑{{ review.user.userprofile.image }}的問題在於,由於用戶是ForeignKey而不是OneToOneField,您的用戶將攜帶userprofile_set屬性。

+0

感謝您的回答。你提到如果我使用當前模型,我可以使用UserProfile.objects.get(user = user),但我認爲我不能在模板中使用它?我沒有選擇個人用戶;我正在選擇多個評論,然後讓用戶查看每條評論。例如,{{review.user}}在我將其放入模板中時工作正常。爲什麼不{{review.user.userprofile.image}}?爲什麼這會與OneToOne配合使用,而不是ForeignKey? – sharataka

+0

如果關係被定義爲OneToOne,那麼您將在用戶上具有單一的「userprofile」屬性作爲反向關係。由於它是一個ForeignKey(許多配置文件可以指向同一個用戶),所以你會得到一個產生查詢集的'userprofile_set'屬性。 – dokkaebi

+0

如果用戶沒有'userprofile'屬性,則{{review.user.userprofile}},{{review.user.userprofile.image}}和{{review.user.userprofile.whatever_else}}都會生成「' 。 Django模板在這方面是寬容的。 – dokkaebi

相關問題